@foldkit/oxlint-plugin 0.10.0-canary.db46ded8d159 → 0.10.0-canary.dc82c7255dbf
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/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@ var __export = (target, all5) => {
|
|
|
4
4
|
__defProp(target, name, { get: all5[name], enumerable: true });
|
|
5
5
|
};
|
|
6
6
|
|
|
7
|
-
// ../../node_modules/.pnpm/effect-oxlint@0.3.
|
|
7
|
+
// ../../node_modules/.pnpm/effect-oxlint@0.3.3_effect@4.0.0-rc.112/node_modules/effect-oxlint/dist/chunk.js
|
|
8
8
|
var __defProp2 = Object.defineProperty;
|
|
9
9
|
var __exportAll = (all5, no_symbols) => {
|
|
10
10
|
let target = {};
|
|
@@ -7399,7 +7399,7 @@ var flatMapEager2 = flatMapEager;
|
|
|
7399
7399
|
var catchEager2 = catchEager;
|
|
7400
7400
|
var fnUntracedEager2 = fnUntracedEager;
|
|
7401
7401
|
|
|
7402
|
-
// ../../node_modules/.pnpm/effect-oxlint@0.3.
|
|
7402
|
+
// ../../node_modules/.pnpm/effect-oxlint@0.3.3_effect@4.0.0-rc.112/node_modules/effect-oxlint/dist/RuleContext.js
|
|
7403
7403
|
var RuleContextBase = Service()("effect-oxlint/RuleContext");
|
|
7404
7404
|
var RuleContext = class extends RuleContextBase {
|
|
7405
7405
|
};
|
|
@@ -10014,7 +10014,7 @@ var updateSomeAndGet = /* @__PURE__ */ dual(2, (self, pf) => sync2(() => {
|
|
|
10014
10014
|
}));
|
|
10015
10015
|
var getUnsafe3 = (self) => self.ref.current;
|
|
10016
10016
|
|
|
10017
|
-
// ../../node_modules/.pnpm/effect-oxlint@0.3.
|
|
10017
|
+
// ../../node_modules/.pnpm/effect-oxlint@0.3.3_effect@4.0.0-rc.112/node_modules/effect-oxlint/dist/index.js
|
|
10018
10018
|
var AST_exports = /* @__PURE__ */ __exportAll({
|
|
10019
10019
|
calleeIdentifier: () => calleeIdentifier,
|
|
10020
10020
|
calleeName: () => calleeName,
|
|
@@ -11086,92 +11086,134 @@ var lazyViewStableReferences = Rule_exports.define({
|
|
|
11086
11086
|
|
|
11087
11087
|
// src/rules/mount-factory-must-use-element.ts
|
|
11088
11088
|
var MOUNT_DEFINITION_METHODS = ["define", "defineStream"];
|
|
11089
|
-
var
|
|
11090
|
-
var
|
|
11091
|
-
var
|
|
11092
|
-
var
|
|
11093
|
-
var
|
|
11094
|
-
|
|
11095
|
-
|
|
11096
|
-
}
|
|
11097
|
-
if (call.callee.type === "CallExpression") {
|
|
11098
|
-
return isMountDefinitionChain(call.callee);
|
|
11099
|
-
}
|
|
11100
|
-
return false;
|
|
11101
|
-
};
|
|
11102
|
-
var returnedFactoryFunction = (statement) => {
|
|
11103
|
-
if (statement.type !== "ReturnStatement" || statement.argument === null) {
|
|
11104
|
-
return Option_exports.none();
|
|
11105
|
-
}
|
|
11106
|
-
return isFactoryFunction(statement.argument) ? Option_exports.some(statement.argument) : Option_exports.none();
|
|
11107
|
-
};
|
|
11108
|
-
var descendToElementFactory = (builder) => {
|
|
11109
|
-
const body = builder.body;
|
|
11110
|
-
if (body === null) return builder;
|
|
11111
|
-
if (isFactoryFunction(body)) return body;
|
|
11112
|
-
if (body.type === "BlockStatement") {
|
|
11113
|
-
return pipe(
|
|
11114
|
-
body.body,
|
|
11115
|
-
Array_exports.findFirst(returnedFactoryFunction),
|
|
11116
|
-
Option_exports.getOrElse(() => builder)
|
|
11117
|
-
);
|
|
11118
|
-
}
|
|
11119
|
-
return builder;
|
|
11120
|
-
};
|
|
11089
|
+
var ELEMENT_FIELD = "element";
|
|
11090
|
+
var NO_ELEMENT_BINDING_MESSAGE = `This Mount's \`execute\` never receives the element: it does not destructure \`element\` from its input. A Mount exists for element-caused, element-targeted work. If the element is irrelevant, use a Command, Subscription, or ManagedResource instead.`;
|
|
11091
|
+
var ignoredElementBindingMessage = (bindingName) => `The element binding \`${bindingName}\` is named as ignored. A Mount's \`execute\` must read or write its live element; if the element does not matter here, the side effect has a different cause and belongs in a Command, Subscription, or ManagedResource.`;
|
|
11092
|
+
var unusedElementBindingMessage = (bindingName) => `The element binding \`${bindingName}\` is never referenced in this Mount's \`execute\`. A Mount's \`execute\` must use its live element; work that does not need the element belongs in a Command, Subscription, or ManagedResource.`;
|
|
11093
|
+
var unreadElementFieldMessage = (bindingName) => `This Mount's \`execute\` reads other fields off \`${bindingName}\` but never its \`element\`. Destructure \`element\` from the input so the check can see the read, or if the element is irrelevant, use a Command, Subscription, or ManagedResource instead.`;
|
|
11094
|
+
var unusedInputMessage = (bindingName) => `This Mount's \`execute\` never references \`${bindingName}\`, so it never reaches the live element. Destructure \`element\` from the input so the check can see the read, or if the element is irrelevant, use a Command, Subscription, or ManagedResource instead.`;
|
|
11095
|
+
var isExecuteFunction = (node) => node.type === "ArrowFunctionExpression" || node.type === "FunctionExpression";
|
|
11121
11096
|
var isRecord = (value) => typeof value === "object" && value !== null;
|
|
11122
|
-
var
|
|
11097
|
+
var shadowsBindingName = (functionNode, bindingName) => {
|
|
11123
11098
|
const parameters = functionNode.params;
|
|
11124
11099
|
if (!isRecord(parameters)) return false;
|
|
11125
11100
|
return Object.values(parameters).some(
|
|
11126
|
-
(parameter) => isRecord(parameter) && parameter.type === "Identifier" && parameter.name ===
|
|
11101
|
+
(parameter) => isRecord(parameter) && parameter.type === "Identifier" && parameter.name === bindingName
|
|
11127
11102
|
);
|
|
11128
11103
|
};
|
|
11129
|
-
var referencesName = (value,
|
|
11104
|
+
var referencesName = (value, bindingName) => {
|
|
11130
11105
|
if (!isRecord(value)) return false;
|
|
11131
|
-
if (value.type === "Identifier" && value.name ===
|
|
11132
|
-
if ((value.type === "ArrowFunctionExpression" || value.type === "FunctionExpression") &&
|
|
11106
|
+
if (value.type === "Identifier" && value.name === bindingName) return true;
|
|
11107
|
+
if ((value.type === "ArrowFunctionExpression" || value.type === "FunctionExpression") && shadowsBindingName(value, bindingName)) {
|
|
11133
11108
|
return false;
|
|
11134
11109
|
}
|
|
11110
|
+
if (value.type === "MemberExpression" && value.computed !== true) {
|
|
11111
|
+
return referencesName(value.object, bindingName);
|
|
11112
|
+
}
|
|
11135
11113
|
if (value.type === "Property") {
|
|
11136
|
-
const computedKeyReferences = value.computed === true && referencesName(value.key,
|
|
11137
|
-
return computedKeyReferences || referencesName(value.value,
|
|
11114
|
+
const computedKeyReferences = value.computed === true && referencesName(value.key, bindingName);
|
|
11115
|
+
return computedKeyReferences || referencesName(value.value, bindingName);
|
|
11138
11116
|
}
|
|
11139
11117
|
return Object.entries(value).some(
|
|
11140
|
-
([key, child]) => key !== "parent" && referencesName(child,
|
|
11118
|
+
([key, child]) => key !== "parent" && referencesName(child, bindingName)
|
|
11141
11119
|
);
|
|
11142
11120
|
};
|
|
11143
|
-
var
|
|
11144
|
-
|
|
11145
|
-
if (
|
|
11146
|
-
|
|
11121
|
+
var inputUses = (value, inputName) => {
|
|
11122
|
+
if (!isRecord(value)) return [];
|
|
11123
|
+
if (value.type === "MemberExpression" && isRecord(value.object) && value.object.type === "Identifier" && value.object.name === inputName) {
|
|
11124
|
+
if (value.computed === true) return ["MaybeElement"];
|
|
11125
|
+
return isRecord(value.property) && value.property.type === "Identifier" && value.property.name === ELEMENT_FIELD ? ["Element"] : ["OtherField"];
|
|
11126
|
+
}
|
|
11127
|
+
if (value.type === "MemberExpression" && value.computed !== true) {
|
|
11128
|
+
return inputUses(value.object, inputName);
|
|
11129
|
+
}
|
|
11130
|
+
if ((value.type === "ArrowFunctionExpression" || value.type === "FunctionExpression") && shadowsBindingName(value, inputName)) {
|
|
11131
|
+
return [];
|
|
11132
|
+
}
|
|
11133
|
+
if (value.type === "Property") {
|
|
11134
|
+
const keyUses = value.computed === true ? inputUses(value.key, inputName) : [];
|
|
11135
|
+
return [...keyUses, ...inputUses(value.value, inputName)];
|
|
11147
11136
|
}
|
|
11148
|
-
if (
|
|
11149
|
-
return
|
|
11137
|
+
if (value.type === "Identifier" && value.name === inputName) {
|
|
11138
|
+
return ["MaybeElement"];
|
|
11150
11139
|
}
|
|
11151
|
-
return
|
|
11140
|
+
return Object.entries(value).flatMap(
|
|
11141
|
+
([key, child]) => key === "parent" ? [] : inputUses(child, inputName)
|
|
11142
|
+
);
|
|
11152
11143
|
};
|
|
11144
|
+
var elementProperty = (pattern) => pipe(
|
|
11145
|
+
pattern.properties,
|
|
11146
|
+
Array_exports.findFirst(
|
|
11147
|
+
(property) => property.type === "Property" && (property.key.type === "Literal" ? property.key.value === ELEMENT_FIELD : !property.computed && property.key.type === "Identifier" && property.key.name === ELEMENT_FIELD)
|
|
11148
|
+
)
|
|
11149
|
+
);
|
|
11150
|
+
var restBindingName = (pattern) => pipe(
|
|
11151
|
+
pattern.properties,
|
|
11152
|
+
Array_exports.findFirst(
|
|
11153
|
+
(property) => property.type === "RestElement" && property.argument.type === "Identifier" ? Option_exports.some(property.argument.name) : Option_exports.none()
|
|
11154
|
+
)
|
|
11155
|
+
);
|
|
11156
|
+
var withoutDefault = (value) => value.type === "AssignmentPattern" ? value.left : value;
|
|
11157
|
+
var bindingDiagnostic = (execute, bindingName) => {
|
|
11158
|
+
if (bindingName.startsWith("_")) {
|
|
11159
|
+
return Option_exports.some(ignoredElementBindingMessage(bindingName));
|
|
11160
|
+
}
|
|
11161
|
+
return referencesName(execute.body, bindingName) ? Option_exports.none() : Option_exports.some(unusedElementBindingMessage(bindingName));
|
|
11162
|
+
};
|
|
11163
|
+
var unpackedDiagnostic = (execute, bindingName) => {
|
|
11164
|
+
const uses = inputUses(execute.body, bindingName);
|
|
11165
|
+
if (Array_exports.isReadonlyArrayEmpty(uses)) {
|
|
11166
|
+
return Option_exports.some(unusedInputMessage(bindingName));
|
|
11167
|
+
}
|
|
11168
|
+
return uses.every((use) => use === "OtherField") ? Option_exports.some(unreadElementFieldMessage(bindingName)) : Option_exports.none();
|
|
11169
|
+
};
|
|
11170
|
+
var executeDiagnostic = (execute) => {
|
|
11171
|
+
const [firstParameter] = execute.params;
|
|
11172
|
+
if (firstParameter === void 0) {
|
|
11173
|
+
return Option_exports.some(NO_ELEMENT_BINDING_MESSAGE);
|
|
11174
|
+
}
|
|
11175
|
+
if (firstParameter.type === "Identifier") {
|
|
11176
|
+
return unpackedDiagnostic(execute, firstParameter.name);
|
|
11177
|
+
}
|
|
11178
|
+
if (firstParameter.type !== "ObjectPattern") {
|
|
11179
|
+
return Option_exports.some(NO_ELEMENT_BINDING_MESSAGE);
|
|
11180
|
+
}
|
|
11181
|
+
return Option_exports.match(elementProperty(firstParameter), {
|
|
11182
|
+
onNone: () => Option_exports.match(restBindingName(firstParameter), {
|
|
11183
|
+
onNone: () => Option_exports.some(NO_ELEMENT_BINDING_MESSAGE),
|
|
11184
|
+
onSome: (restName) => unpackedDiagnostic(execute, restName)
|
|
11185
|
+
}),
|
|
11186
|
+
onSome: (property) => {
|
|
11187
|
+
const pattern = withoutDefault(property.value);
|
|
11188
|
+
return pattern.type === "Identifier" ? bindingDiagnostic(execute, pattern.name) : Option_exports.none();
|
|
11189
|
+
}
|
|
11190
|
+
});
|
|
11191
|
+
};
|
|
11192
|
+
var executeFunction = (node) => pipe(
|
|
11193
|
+
Array_exports.get(node.arguments, 1),
|
|
11194
|
+
Option_exports.filter(isObjectExpression),
|
|
11195
|
+
Option_exports.flatMap((config) => AST_exports.objectGetValue(config, "execute")),
|
|
11196
|
+
Option_exports.filter(isExecuteFunction)
|
|
11197
|
+
);
|
|
11153
11198
|
var mountFactoryMustUseElement = Rule_exports.define({
|
|
11154
11199
|
name: "mount-factory-must-use-element",
|
|
11155
11200
|
meta: Rule_exports.meta({
|
|
11156
11201
|
type: "suggestion",
|
|
11157
|
-
description: "Require Mount
|
|
11202
|
+
description: "Require a Mount's execute to use its live element."
|
|
11158
11203
|
}),
|
|
11159
11204
|
create: function* () {
|
|
11160
11205
|
const ctx = yield* RuleContext;
|
|
11161
11206
|
return {
|
|
11162
11207
|
CallExpression: (node) => {
|
|
11163
|
-
if (!isCallExpression(node)
|
|
11164
|
-
if (node.callee.type !== "CallExpression" || !isMountDefinitionChain(node.callee)) {
|
|
11165
|
-
return Effect_exports.void;
|
|
11166
|
-
}
|
|
11167
|
-
const [factoryArgument] = node.arguments;
|
|
11168
|
-
if (factoryArgument === void 0 || !isFactoryFunction(factoryArgument)) {
|
|
11208
|
+
if (!isCallExpression(node) || !AST_exports.isCallOf(node, "Mount", MOUNT_DEFINITION_METHODS)) {
|
|
11169
11209
|
return Effect_exports.void;
|
|
11170
11210
|
}
|
|
11171
|
-
|
|
11172
|
-
return Option_exports.match(elementFactoryDiagnostic(elementFactory), {
|
|
11211
|
+
return Option_exports.match(executeFunction(node), {
|
|
11173
11212
|
onNone: () => Effect_exports.void,
|
|
11174
|
-
onSome: (
|
|
11213
|
+
onSome: (execute) => Option_exports.match(executeDiagnostic(execute), {
|
|
11214
|
+
onNone: () => Effect_exports.void,
|
|
11215
|
+
onSome: (message) => ctx.report(Diagnostic_exports.make({ node: execute, message }))
|
|
11216
|
+
})
|
|
11175
11217
|
});
|
|
11176
11218
|
}
|
|
11177
11219
|
};
|
|
@@ -11456,7 +11498,7 @@ var noDisablingDevGuardrails = Rule_exports.define({
|
|
|
11456
11498
|
});
|
|
11457
11499
|
|
|
11458
11500
|
// src/rules/no-duplicate-onmount-per-element.ts
|
|
11459
|
-
var DUPLICATE_ON_MOUNT_MESSAGE = "Only one OnMount attribute can attach to an element. Foldkit installs a single insert hook and tracks a single Mount fiber per element, so a later OnMount replaces the earlier one and its
|
|
11501
|
+
var DUPLICATE_ON_MOUNT_MESSAGE = "Only one OnMount attribute can attach to an element. Foldkit installs a single insert hook and tracks a single Mount fiber per element, so a later OnMount replaces the earlier one and its `execute` never runs. Combine the behaviors into one Mount definition.";
|
|
11460
11502
|
var isOnMountCallee = (callee) => {
|
|
11461
11503
|
if (callee.type === "Identifier") {
|
|
11462
11504
|
return callee.name === "OnMount";
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
/** Flags
|
|
1
|
+
/** Flags Mount.define and Mount.defineStream definitions whose `execute` never uses its element. A Mount exists for element-caused, element-targeted work; work that ignores the element belongs in a Command, Subscription, or ManagedResource. */
|
|
2
2
|
export declare const mountFactoryMustUseElement: import("effect-oxlint").CreateRule;
|
|
3
3
|
//# sourceMappingURL=mount-factory-must-use-element.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mount-factory-must-use-element.d.ts","sourceRoot":"","sources":["../../src/rules/mount-factory-must-use-element.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"mount-factory-must-use-element.d.ts","sourceRoot":"","sources":["../../src/rules/mount-factory-must-use-element.ts"],"names":[],"mappings":"AA0NA,oPAAoP;AACpP,eAAO,MAAM,0BAA0B,oCA4BrC,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@foldkit/oxlint-plugin",
|
|
3
|
-
"version": "0.10.0-canary.
|
|
3
|
+
"version": "0.10.0-canary.dc82c7255dbf",
|
|
4
4
|
"description": "Oxlint rules for Foldkit applications",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -15,15 +15,15 @@
|
|
|
15
15
|
"./all.json": "./all.json"
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"effect-oxlint": "^0.3.
|
|
18
|
+
"effect-oxlint": "^0.3.3"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
21
|
-
"@types/node": "^25.9.
|
|
21
|
+
"@types/node": "^25.9.5",
|
|
22
22
|
"effect": "4.0.0-rc.112",
|
|
23
|
-
"esbuild": "^0.28.
|
|
23
|
+
"esbuild": "^0.28.2",
|
|
24
24
|
"rimraf": "^6.1.3",
|
|
25
25
|
"typescript": "^6.0.3",
|
|
26
|
-
"vitest": "^4.1.
|
|
26
|
+
"vitest": "^4.1.11"
|
|
27
27
|
},
|
|
28
28
|
"files": [
|
|
29
29
|
"dist",
|