@onrails/codemod 0.2.2 → 0.2.4
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/package.json +1 -1
- package/src/boundary-spec.ts +37 -0
package/package.json
CHANGED
package/src/boundary-spec.ts
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* 1. no `Promise<Result<…>>` in public signatures (`no-promise-result`)
|
|
6
6
|
* 2. no unsafe unwraps outside tests (`no-unsafe-unwrap`)
|
|
7
7
|
* 3. no deprecated neverthrow-era synonyms (`no-deprecated-synonyms`)
|
|
8
|
+
* 4. the fluent wrapper stays local (`fluent-stays-local`)
|
|
8
9
|
*
|
|
9
10
|
* The ESLint plugin (plain JS, `packages/eslint-plugin/src/index.js`) and the
|
|
10
11
|
* Biome plugin (GritQL, `packages/biome-plugin/rules/*.grit`) cannot import
|
|
@@ -122,6 +123,29 @@ export const NO_DEPRECATED_SYNONYMS_RULE = {
|
|
|
122
123
|
id: "no-deprecated-synonyms",
|
|
123
124
|
} as const;
|
|
124
125
|
|
|
126
|
+
// ---------------------------------------------------------------------------
|
|
127
|
+
// Fluent locality (RFC 0002 §9 rule 2)
|
|
128
|
+
// ---------------------------------------------------------------------------
|
|
129
|
+
|
|
130
|
+
/** The opt-in dot-chaining wrapper types — must open and close within a function body. */
|
|
131
|
+
export const FLUENT_WRAPPER_TYPES = ["FluentResult", "FluentMaybe"] as const;
|
|
132
|
+
|
|
133
|
+
/** Call targets treated as serialization/transfer sinks for the escape check. */
|
|
134
|
+
export const FLUENT_ESCAPE_SINK_NAMES = [
|
|
135
|
+
"postMessage",
|
|
136
|
+
"structuredClone",
|
|
137
|
+
"JSON.stringify",
|
|
138
|
+
] as const;
|
|
139
|
+
|
|
140
|
+
/** The fluent wrapper escaping its function — return type, export, field, or serialize-sink argument. */
|
|
141
|
+
export const FLUENT_STAYS_LOCAL_RULE = {
|
|
142
|
+
id: "fluent-stays-local",
|
|
143
|
+
wrapperTypes: FLUENT_WRAPPER_TYPES,
|
|
144
|
+
sinks: FLUENT_ESCAPE_SINK_NAMES,
|
|
145
|
+
message:
|
|
146
|
+
"FluentResult/FluentMaybe must stay local — it was flagged as a return type, an exported binding, a stored field, or an argument to a serialize/postMessage/cache call. Call toResult()/toMaybe()/toString() before it leaves the function.",
|
|
147
|
+
} as const;
|
|
148
|
+
|
|
125
149
|
// ---------------------------------------------------------------------------
|
|
126
150
|
// Declared divergences
|
|
127
151
|
// ---------------------------------------------------------------------------
|
|
@@ -150,4 +174,17 @@ export const ENGINE_DIVERGENCES: readonly EngineDivergence[] = [
|
|
|
150
174
|
"flags test code too. Suppress with a biome-ignore comment or a linter " +
|
|
151
175
|
"override for test globs.",
|
|
152
176
|
},
|
|
177
|
+
{
|
|
178
|
+
rule: FLUENT_STAYS_LOCAL_RULE.id,
|
|
179
|
+
engine: "biome",
|
|
180
|
+
divergence: "no-position-scoping",
|
|
181
|
+
detail:
|
|
182
|
+
"The ESLint rule only flags FluentResult/FluentMaybe in the four scoped " +
|
|
183
|
+
"positions (return type, exported binding, stored field, serialize-sink " +
|
|
184
|
+
"argument) and inspects call-argument shape for the sink check. GritQL " +
|
|
185
|
+
"matches the bare type reference wherever it appears — a broader net " +
|
|
186
|
+
"that also catches local annotations the ESLint rule leaves alone — and " +
|
|
187
|
+
"cannot express the serialize/postMessage/cache argument heuristic at " +
|
|
188
|
+
"all, since that needs expression-shape traversal, not a type pattern.",
|
|
189
|
+
},
|
|
153
190
|
];
|