@deslop/coding-standards 0.1.1242 → 0.1.1244
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/README.md +5 -4
- package/dist/install.js +1 -1
- package/dist/lint.js +299 -131
- package/package.json +3 -3
- package/tsconfig.json +0 -184
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @deslop/coding-standards
|
|
2
2
|
|
|
3
|
-
A Vite+ lint preset, a strict TypeScript configuration
|
|
3
|
+
A Vite+ lint preset that runs the Effect rules and TypeScript diagnostics in Oxlint on tsrs, a strict TypeScript configuration, and the `lint-companion`, `pull-requests` and `review` skills for Claude Code and Codex.
|
|
4
4
|
|
|
5
5
|
```bash
|
|
6
6
|
vpx @deslop/coding-standards@latest # installs the skills
|
|
@@ -20,13 +20,14 @@ export default defineConfig({lint: {extends: [lint]}})
|
|
|
20
20
|
// package.json
|
|
21
21
|
{
|
|
22
22
|
"scripts": {
|
|
23
|
-
"prepare": "effect-tsgo patch --no-typescript --tsrs",
|
|
24
|
-
"
|
|
25
|
-
"check": "vp check && vp run typecheck"
|
|
23
|
+
"prepare": "effect-tsgo patch --no-typescript --tsrs --oxlint",
|
|
24
|
+
"check": "effect-tsgo --tsrs-lint vp lint --type-aware --type-check"
|
|
26
25
|
}
|
|
27
26
|
}
|
|
28
27
|
```
|
|
29
28
|
|
|
29
|
+
The preset leaves type-aware lint and type checking off, so a syntax-only pass stays possible; the two flags turn them on, and `--tsrs-lint` runs them on tsrs instead of Oxlint's tsgolint backend.
|
|
30
|
+
|
|
30
31
|
```jsonc
|
|
31
32
|
// tsconfig.json
|
|
32
33
|
{"extends": "@deslop/coding-standards/tsconfig.json"}
|
package/dist/install.js
CHANGED
|
@@ -27604,7 +27604,7 @@ const runWith = (command, config) => {
|
|
|
27604
27604
|
}, ({ error, userMessage }) => andThen(showUserError(error, userMessage), fail$3(error))), catchFilter((e) => isQuitError(e) ? succeed$6(e) : fail$8(e), (_) => interrupt$1));
|
|
27605
27605
|
};
|
|
27606
27606
|
// package.json
|
|
27607
|
-
var version = "0.1.
|
|
27607
|
+
var version = "0.1.1244";
|
|
27608
27608
|
// src/install.ts
|
|
27609
27609
|
const cli = pipe(make("deslop-coding-standards", {}, fnUntraced(function* () {
|
|
27610
27610
|
const fs = yield* FileSystem;
|
package/dist/lint.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as join, A as dedupe, At as all, B as findFirstIndex, Br as isRegExp, Bt as getOrElse, C as TaggedError, D as contains, E as appendAll, Er as hasProperty, F as ensure, Fr as isNullish, Ft as firstSomeOf, Gr as constFalse, Gt as liftThrowable, H as flatMap, Ht as isNone, I as every, Ir as isNumber$1, It as flatMap$1, J as head, Jr as constVoid, Jt as none, K as get$3, Kt as map
|
|
1
|
+
import { $ as join, A as dedupe, At as all, B as findFirstIndex, Br as isRegExp, Bt as getOrElse, C as TaggedError, D as contains, E as appendAll, Er as hasProperty, F as ensure, Fr as isNullish, Ft as firstSomeOf, Gr as constFalse, Gt as liftThrowable, H as flatMap, Ht as isNone, I as every, Ir as isNumber$1, It as flatMap$1, J as head, Jr as constVoid, Jt as none, K as get$3, Kt as map, L as filter$1, Lt as flatten$1, M as drop, Mr as isNotNull, Mt as contains$1, N as dropRight, Nr as isNotNullish, Nt as exists, O as containsWith, Or as isBoolean, P as empty$2, Pt as filter, Q as isReadonlyArrayNonEmpty, Qt as zipWith, R as filterMap, Rt as fromNullishOr, Sr as string, St as fromOption, T as append, Tr as symbol$1, U as flatten, Ut as isSome, Vr as isString, Vt as getOrUndefined, W as forEach, Wt as liftPredicate, X as isArrayNonEmpty, Xr as dual, Xt as some, Y as isArrayEmpty, Yt as orElse, Zt as toArray$1, _ as toUpperCase, ar as format, at as of, b as parse, br as number, c as Order, ct as some$1, d as match$1, dt as takeWhile, ei as pipe, et as last, f as matchAll, ft as zip, g as startsWith, gr as symbol, h as split, hr as equals, ht as has$2, i as make$2, it as matchRight, j as dedupeWith, jt as as, k as countBy, l as includes, lt as sort, m as slice, mr as byReferenceUnsafe, mt as get$2, n as append$1, nr as NodeInspectSymbol, nt as map$1, ot as prepend, p as replaceAll, pt as fromEntries, q as getSomes, qt as match, ri as pipeArguments, rr as toJson, s as toArray, t as match$2, u as isNonEmpty, un as strictEqual, ut as take, v as trim, vr as combine, vt as mapEntries, xr as optimize, yr as hash, z as findFirst, zt as fromUndefinedOr } from "./Boolean-C8Zb2yak.mjs";
|
|
2
2
|
import { definePlugin, defineRule } from "vite-plus/lint/plugins";
|
|
3
3
|
// ../../node_modules/.pnpm/effect@4.1.2/node_modules/effect/dist/MutableHashMap.js
|
|
4
4
|
const TypeId$2 = "~effect/MutableHashMap";
|
|
@@ -962,6 +962,12 @@ function variableFromScope(input) {
|
|
|
962
962
|
function boundVariable(input) {
|
|
963
963
|
return filter(variableFromScope(input), (variable) => isArrayNonEmpty(variable.defs) || isArrayNonEmpty(variable.references));
|
|
964
964
|
}
|
|
965
|
+
function readsOf(input) {
|
|
966
|
+
return pipe(variableFromScope({
|
|
967
|
+
name: input.name,
|
|
968
|
+
scope: input.context.sourceCode.getScope(input.node)
|
|
969
|
+
}), map((variable) => filter$1(variable.references, (reference) => reference.isRead())));
|
|
970
|
+
}
|
|
965
971
|
function variableFor(context, node) {
|
|
966
972
|
return variableFromScope({
|
|
967
973
|
name: node.name,
|
|
@@ -971,7 +977,7 @@ function variableFor(context, node) {
|
|
|
971
977
|
const importedNames = /* @__PURE__ */ new WeakMap();
|
|
972
978
|
function importNames(statements) {
|
|
973
979
|
return flatMap(statements, (statement) => {
|
|
974
|
-
if (statement.type === "ImportDeclaration") return map(statement.specifiers, (specifier) => specifier.local.name);
|
|
980
|
+
if (statement.type === "ImportDeclaration") return map$1(statement.specifiers, (specifier) => specifier.local.name);
|
|
975
981
|
if (statement.type === "TSModuleDeclaration" && statement.body?.type === "TSModuleBlock") return importNames(statement.body.body);
|
|
976
982
|
return [];
|
|
977
983
|
});
|
|
@@ -1004,8 +1010,8 @@ function effectImport(input) {
|
|
|
1004
1010
|
}), filter((variable) => isArrayNonEmpty(variable.defs)), match({
|
|
1005
1011
|
onNone: () => pipe(input.context.sourceCode.ast.body, findFirst((statement) => statement.type === "ImportDeclaration" && statement.source.value === "effect" && statement.importKind !== "type" && every(statement.specifiers, (specifier) => specifier.type === "ImportSpecifier")), flatMap$1((statement) => {
|
|
1006
1012
|
if (statement.type !== "ImportDeclaration") return none();
|
|
1007
|
-
return pipe(findFirst(statement.specifiers, (specifier) => Order(importedName(specifier), input.name) > 0), map
|
|
1008
|
-
}), orElse(() => map
|
|
1013
|
+
return pipe(findFirst(statement.specifiers, (specifier) => Order(importedName(specifier), input.name) > 0), map((specifier) => input.fixer.insertTextBefore(specifier, `${input.name}, `)), orElse(() => map(last(statement.specifiers), (specifier) => input.fixer.insertTextAfter(specifier, `, ${input.name}`))));
|
|
1014
|
+
}), orElse(() => map(findFirst(input.context.sourceCode.ast.body, (statement) => statement.type !== "ExpressionStatement" || isNullish(statement.directive)), (statement) => input.fixer.insertTextBefore(statement, `import {${input.name}} from 'effect'\n`))), map(of)),
|
|
1009
1015
|
onSome: (variable) => liftPredicate(empty$2(), () => some$1(variable.defs, (definition) => definition.type === "ImportBinding" && definition.parent?.type === "ImportDeclaration" && definition.parent.source.value === "effect" && definition.parent.importKind !== "type" && definition.node.type === "ImportSpecifier" && definition.node.importKind !== "type" && definition.node.imported.type === "Identifier" && definition.node.imported.name === input.name))
|
|
1010
1016
|
}));
|
|
1011
1017
|
}
|
|
@@ -1066,11 +1072,11 @@ function chainOf(node) {
|
|
|
1066
1072
|
members: [],
|
|
1067
1073
|
root: node
|
|
1068
1074
|
});
|
|
1069
|
-
if (node.type === "MemberExpression") return flatMap$1(memberName(node), (name) => map
|
|
1075
|
+
if (node.type === "MemberExpression") return flatMap$1(memberName(node), (name) => map(chainOf(node.object), (chain) => ({
|
|
1070
1076
|
...chain,
|
|
1071
1077
|
members: append(chain.members, name)
|
|
1072
1078
|
})));
|
|
1073
|
-
if (node.type === "CallExpression") return map
|
|
1079
|
+
if (node.type === "CallExpression") return map(chainOf(node.callee), (chain) => ({
|
|
1074
1080
|
...chain,
|
|
1075
1081
|
calls: append(chain.calls, node)
|
|
1076
1082
|
}));
|
|
@@ -1133,7 +1139,7 @@ function propertyKey(property) {
|
|
|
1133
1139
|
}
|
|
1134
1140
|
function optionKeys(node) {
|
|
1135
1141
|
if (node.type !== "ObjectExpression") return empty$2();
|
|
1136
|
-
return getSomes(map(node.properties, propertyKey));
|
|
1142
|
+
return getSomes(map$1(node.properties, propertyKey));
|
|
1137
1143
|
}
|
|
1138
1144
|
function isTestClockMember(context, node, propertyName) {
|
|
1139
1145
|
return node.type === "MemberExpression" && node.object.type === "Identifier" && contains$1(memberName(node), propertyName) && isImportBinding({
|
|
@@ -1165,6 +1171,14 @@ function importedMember(input) {
|
|
|
1165
1171
|
source: "effect"
|
|
1166
1172
|
});
|
|
1167
1173
|
}
|
|
1174
|
+
function effectMethod(input) {
|
|
1175
|
+
if (input.node.callee.type !== "MemberExpression" || !importedMember({
|
|
1176
|
+
context: input.context,
|
|
1177
|
+
importedName: "Effect",
|
|
1178
|
+
node: input.node.callee
|
|
1179
|
+
})) return none();
|
|
1180
|
+
return memberName(input.node.callee);
|
|
1181
|
+
}
|
|
1168
1182
|
function isWriteTarget(node) {
|
|
1169
1183
|
if (node.parent === null) return false;
|
|
1170
1184
|
return (node.parent.type === "AssignmentExpression" || node.parent.type === "AssignmentPattern") && node.parent.left === node || node.parent.type === "ArrayPattern" || node.parent.type === "RestElement" || node.parent.type === "Property" && node.parent.value === node && node.parent.parent.type === "ObjectPattern" || (node.parent.type === "ForInStatement" || node.parent.type === "ForOfStatement") && node.parent.left === node || node.parent.type === "UpdateExpression" || node.parent.type === "UnaryExpression" && node.parent.operator === "delete";
|
|
@@ -1266,12 +1280,12 @@ function suspendedTypeName(input) {
|
|
|
1266
1280
|
}
|
|
1267
1281
|
function memberType(member) {
|
|
1268
1282
|
if (member.type === "TSIndexSignature") return some(member.typeAnnotation.typeAnnotation);
|
|
1269
|
-
if (member.type === "TSPropertySignature") return map
|
|
1270
|
-
return map
|
|
1283
|
+
if (member.type === "TSPropertySignature") return map(fromNullishOr(member.typeAnnotation), (annotation) => annotation.typeAnnotation);
|
|
1284
|
+
return map(fromNullishOr(member.returnType), (annotation) => annotation.typeAnnotation);
|
|
1271
1285
|
}
|
|
1272
1286
|
function referencedTypeNames(node) {
|
|
1273
1287
|
if (node.type === "TSTypeReference") {
|
|
1274
|
-
const argumentNames = pipe(fromNullishOr(node.typeArguments), map
|
|
1288
|
+
const argumentNames = pipe(fromNullishOr(node.typeArguments), map((typeArguments) => pipe(typeArguments.params, flatMap(referencedTypeNames))), getOrElse(() => empty$2()));
|
|
1275
1289
|
if (node.typeName.type !== "Identifier") return argumentNames;
|
|
1276
1290
|
return prepend(argumentNames, node.typeName.name);
|
|
1277
1291
|
}
|
|
@@ -1293,8 +1307,8 @@ function referencedTypeNames(node) {
|
|
|
1293
1307
|
node.constraint,
|
|
1294
1308
|
node.nameType,
|
|
1295
1309
|
node.typeAnnotation
|
|
1296
|
-
], map((child) => fromNullishOr(child)), getSomes, flatMap(referencedTypeNames));
|
|
1297
|
-
if (node.type === "TSTypeLiteral") return pipe(node.members, map(memberType), getSomes, flatMap(referencedTypeNames));
|
|
1310
|
+
], map$1((child) => fromNullishOr(child)), getSomes, flatMap(referencedTypeNames));
|
|
1311
|
+
if (node.type === "TSTypeLiteral") return pipe(node.members, map$1(memberType), getSomes, flatMap(referencedTypeNames));
|
|
1298
1312
|
return empty$2();
|
|
1299
1313
|
}
|
|
1300
1314
|
function isNode(value) {
|
|
@@ -1379,12 +1393,12 @@ function schemaEdges(context, statement) {
|
|
|
1379
1393
|
function schemaCycleNames(input) {
|
|
1380
1394
|
if (isArrayEmpty(input.seeds) || !some$1(input.program.body, (statement) => statement.type === "ImportDeclaration" && statement.source.value === "effect" && some$1(statement.specifiers, (specifier) => specifier.type === "ImportSpecifier" && specifier.imported.type === "Identifier" && specifier.imported.name === "Schema"))) return empty$2();
|
|
1381
1395
|
const edges = pipe(input.program.body, flatMap((statement) => schemaEdges(input.context, statement)));
|
|
1382
|
-
const names = pipe(edges, map((edge) => edge.name), dedupe);
|
|
1396
|
+
const names = pipe(edges, map$1((edge) => edge.name), dedupe);
|
|
1383
1397
|
const graph = directed((mutable) => {
|
|
1384
|
-
const indices = fromEntries(map(names, (name) => [name, addNode(mutable, name)]));
|
|
1398
|
+
const indices = fromEntries(map$1(names, (name) => [name, addNode(mutable, name)]));
|
|
1385
1399
|
for (const edge of edges) for (const target of edge.targets) zipWith(get$2(indices, edge.name), get$2(indices, target), (source, sink) => addEdge(mutable, source, sink, "reads"));
|
|
1386
1400
|
});
|
|
1387
|
-
return pipe(stronglyConnectedComponents(graph), map((component) => getSomes(map(component, (index) => getNode(graph, index)))), filter$1((component) => (component.length > 1 || some$1(edges, (edge) => contains(component, edge.name) && contains(edge.targets, edge.name))) && some$1(component, (name) => contains(input.seeds, name))), flatten);
|
|
1401
|
+
return pipe(stronglyConnectedComponents(graph), map$1((component) => getSomes(map$1(component, (index) => getNode(graph, index)))), filter$1((component) => (component.length > 1 || some$1(edges, (edge) => contains(component, edge.name) && contains(edge.targets, edge.name))) && some$1(component, (name) => contains(input.seeds, name))), flatten);
|
|
1388
1402
|
}
|
|
1389
1403
|
function suspends(context, node) {
|
|
1390
1404
|
if (node.type === "YieldExpression" || node.type === "AwaitExpression") return true;
|
|
@@ -1432,12 +1446,16 @@ function bindingName(node) {
|
|
|
1432
1446
|
if (node.parent.type === "VariableDeclarator" && node.parent.id.type === "Identifier") return some(node.parent.id.name);
|
|
1433
1447
|
return none();
|
|
1434
1448
|
}
|
|
1449
|
+
function boundReads(input) {
|
|
1450
|
+
return pipe(bindingName(input.node), flatMap$1((name) => readsOf({
|
|
1451
|
+
context: input.context,
|
|
1452
|
+
name,
|
|
1453
|
+
node: input.node
|
|
1454
|
+
})));
|
|
1455
|
+
}
|
|
1435
1456
|
function singleUseThunk(input) {
|
|
1436
1457
|
if (isReadonlyArrayNonEmpty(input.node.params) || input.node.typeParameters !== null || !hasSingleStatementExpression(input.node)) return false;
|
|
1437
|
-
return
|
|
1438
|
-
name,
|
|
1439
|
-
scope: input.context.sourceCode.getScope(input.node)
|
|
1440
|
-
})), exists((variable) => countBy(variable.references, (reference) => reference.isRead()) === 1));
|
|
1458
|
+
return exists(boundReads(input), (reads) => reads.length === 1);
|
|
1441
1459
|
}
|
|
1442
1460
|
// src/rules/explicit-effect-concurrency.ts
|
|
1443
1461
|
function statesConcurrency(node) {
|
|
@@ -1477,13 +1495,11 @@ function isFunction(context, node) {
|
|
|
1477
1495
|
}
|
|
1478
1496
|
const explicitEffectConcurrency = defineRule({
|
|
1479
1497
|
create: (context) => ({ CallExpression: (node) => {
|
|
1480
|
-
|
|
1481
|
-
const name = memberName(node.callee);
|
|
1482
|
-
if (!exists(name, (method) => method === "all" || method === "forEach") || !importedMember({
|
|
1498
|
+
const name = effectMethod({
|
|
1483
1499
|
context,
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1500
|
+
node
|
|
1501
|
+
});
|
|
1502
|
+
if (!exists(name, (method) => method === "all" || method === "forEach")) return;
|
|
1487
1503
|
const index = match$2(contains$1(name, "all") || isFunction(context, node.arguments[0]) || node.arguments[1]?.type === "ObjectExpression", {
|
|
1488
1504
|
onFalse: () => 2,
|
|
1489
1505
|
onTrue: () => 1
|
|
@@ -1622,14 +1638,14 @@ function check$3(input) {
|
|
|
1622
1638
|
}
|
|
1623
1639
|
if (!isConstantName(input.found.id.name)) {
|
|
1624
1640
|
const name = pipe(input.found.id.name, replaceAll(/(?<=[a-z0-9])(?=[A-Z])/gu, "_"), toUpperCase);
|
|
1625
|
-
const taken = some$1([input.found.id, ...map(input.variable.references, (reference) => reference.identifier)], (node) => isSome(variableFromScope({
|
|
1641
|
+
const taken = some$1([input.found.id, ...map$1(input.variable.references, (reference) => reference.identifier)], (node) => isSome(variableFromScope({
|
|
1626
1642
|
name,
|
|
1627
1643
|
scope: input.context.sourceCode.getScope(node)
|
|
1628
1644
|
})));
|
|
1629
1645
|
input.context.report({
|
|
1630
1646
|
fix: (fixer) => {
|
|
1631
1647
|
if (taken) return [];
|
|
1632
|
-
return [fixer.replaceTextRange([input.found.id.range[0], input.found.id.range[0] + input.found.id.name.length], name), ...pipe(input.variable.references, filter$1((reference) => reference.identifier !== input.found.id), map((reference) => renamed({
|
|
1648
|
+
return [fixer.replaceTextRange([input.found.id.range[0], input.found.id.range[0] + input.found.id.name.length], name), ...pipe(input.variable.references, filter$1((reference) => reference.identifier !== input.found.id), map$1((reference) => renamed({
|
|
1633
1649
|
fixer,
|
|
1634
1650
|
name,
|
|
1635
1651
|
reference
|
|
@@ -1646,11 +1662,11 @@ function check$3(input) {
|
|
|
1646
1662
|
}
|
|
1647
1663
|
const moduleConstant = defineRule({
|
|
1648
1664
|
create: (context) => ({ Program: (program) => {
|
|
1649
|
-
const leadingEnd = pipe(program.body, takeWhile((statement) => statement.type === "ImportDeclaration" || isSome(literalConstant(statement))), last, map
|
|
1665
|
+
const leadingEnd = pipe(program.body, takeWhile((statement) => statement.type === "ImportDeclaration" || isSome(literalConstant(statement))), last, map((statement) => statement.range[1]), getOrElse(() => 0));
|
|
1650
1666
|
for (const statement of program.body) pipe(literalConstant(statement), flatMap$1((found) => pipe(variableFromScope({
|
|
1651
1667
|
name: found.id.name,
|
|
1652
1668
|
scope: context.sourceCode.getScope(found.node)
|
|
1653
|
-
}), filter((variable) => !some$1(variable.references, (reference) => reference.identifier.parent.type === "ExportSpecifier")), map
|
|
1669
|
+
}), filter((variable) => !some$1(variable.references, (reference) => reference.identifier.parent.type === "ExportSpecifier")), map((variable) => ({
|
|
1654
1670
|
found,
|
|
1655
1671
|
variable
|
|
1656
1672
|
})))), match({
|
|
@@ -1670,7 +1686,7 @@ const moduleConstant = defineRule({
|
|
|
1670
1686
|
// src/rules/motion-limits.ts
|
|
1671
1687
|
const MOTION_UTILITY = /duration-|zoom-|scale-/u;
|
|
1672
1688
|
function amount(token, pattern) {
|
|
1673
|
-
return pipe(token, match$1(pattern), flatMap$1((match) => fromNullishOr(match[1])), map
|
|
1689
|
+
return pipe(token, match$1(pattern), flatMap$1((match) => fromNullishOr(match[1])), map((value) => pipe(parse(value), getOrElse(() => 0))));
|
|
1674
1690
|
}
|
|
1675
1691
|
function violation(token) {
|
|
1676
1692
|
const name = pipe(token, split(":"), last, getOrElse(() => token), replaceAll(/^!|!$/gu, ""));
|
|
@@ -1681,7 +1697,7 @@ function violation(token) {
|
|
|
1681
1697
|
}
|
|
1682
1698
|
function check$2(context, node, text) {
|
|
1683
1699
|
if (!MOTION_UTILITY.test(text)) return;
|
|
1684
|
-
pipe(split(text, /\s+/u), findFirst(violation), map
|
|
1700
|
+
pipe(split(text, /\s+/u), findFirst(violation), map((message) => context.report({
|
|
1685
1701
|
message,
|
|
1686
1702
|
node
|
|
1687
1703
|
})));
|
|
@@ -1776,8 +1792,8 @@ const noAccumulatingCopy = defineRule({
|
|
|
1776
1792
|
pipe(variableFromScope({
|
|
1777
1793
|
name: parameter.name,
|
|
1778
1794
|
scope: context.sourceCode.getScope(callback)
|
|
1779
|
-
}), map
|
|
1780
|
-
for (const reference of variable.references) pipe(copySite(context, reference.identifier), filter((copy) => !has(reported, copy.range[0])), map
|
|
1795
|
+
}), map((variable) => {
|
|
1796
|
+
for (const reference of variable.references) pipe(copySite(context, reference.identifier), filter((copy) => !has(reported, copy.range[0])), map((copy) => {
|
|
1781
1797
|
add(reported, copy.range[0]);
|
|
1782
1798
|
context.report({
|
|
1783
1799
|
message: "Copying the accumulator in a fold can make collection building quadratic. Prefer Array.map/filterMap/flatMap/groupBy, Record.fromEntries, Array.mapAccum, or a local MutableList/MutableHashMap collector.",
|
|
@@ -1850,10 +1866,7 @@ const noComponentAtomAllocation = defineRule({
|
|
|
1850
1866
|
function isConstantFunction(input) {
|
|
1851
1867
|
if (input.node.async || input.node.generator || isArrayNonEmpty(input.node.params) || isNotNullish(input.node.typeParameters)) return false;
|
|
1852
1868
|
const returned = returnedExpression(input.node);
|
|
1853
|
-
return isNotNullish(returned) && (returned.type === "Literal" && !hasProperty(returned, "regex") || returned.type === "TemplateLiteral" && isArrayEmpty(returned.expressions)) &&
|
|
1854
|
-
name,
|
|
1855
|
-
scope: input.context.sourceCode.getScope(input.node)
|
|
1856
|
-
})), exists((variable) => every(filter$1(variable.references, (reference) => reference.isRead()), (reference) => reference.identifier.parent.type === "CallExpression" && reference.identifier.parent.callee === reference.identifier)));
|
|
1869
|
+
return isNotNullish(returned) && (returned.type === "Literal" && !hasProperty(returned, "regex") || returned.type === "TemplateLiteral" && isArrayEmpty(returned.expressions)) && exists(boundReads(input), (reads) => every(reads, (reference) => reference.identifier.parent.type === "CallExpression" && reference.identifier.parent.callee === reference.identifier));
|
|
1857
1870
|
}
|
|
1858
1871
|
function isConstBound(node) {
|
|
1859
1872
|
return node.parent.type === "VariableDeclarator" && node.parent.parent.type === "VariableDeclaration" && node.parent.parent.kind === "const";
|
|
@@ -2041,7 +2054,7 @@ function operands(input) {
|
|
|
2041
2054
|
function comparedNullish(input) {
|
|
2042
2055
|
if (input.node.type !== "BinaryExpression" || input.node.operator !== input.operator) return none();
|
|
2043
2056
|
const subject = input.node.left;
|
|
2044
|
-
return map
|
|
2057
|
+
return map(nullishOperand({
|
|
2045
2058
|
context: input.context,
|
|
2046
2059
|
node: input.node.right
|
|
2047
2060
|
}), (nullish) => ({
|
|
@@ -2059,7 +2072,7 @@ function guardCall(input) {
|
|
|
2059
2072
|
first: input.checks[0],
|
|
2060
2073
|
second: input.checks[1]
|
|
2061
2074
|
}) || input.context.sourceCode.getTokensBetween(input.checks[0].node, input.checks[1].node).length !== 1) return none();
|
|
2062
|
-
return map
|
|
2075
|
+
return map(effectImport({
|
|
2063
2076
|
context: input.context,
|
|
2064
2077
|
fixer: input.fixer,
|
|
2065
2078
|
name: "Predicate",
|
|
@@ -2071,7 +2084,7 @@ const noDoubleNullishCheck = defineRule({
|
|
|
2071
2084
|
if (node.operator === "??") return;
|
|
2072
2085
|
if (node.parent.type === "LogicalExpression" && node.parent.operator === node.operator) return;
|
|
2073
2086
|
const variant = VARIANTS[node.operator];
|
|
2074
|
-
const checks = map(operands({
|
|
2087
|
+
const checks = map$1(operands({
|
|
2075
2088
|
node,
|
|
2076
2089
|
operator: node.operator
|
|
2077
2090
|
}), (operand) => comparedNullish({
|
|
@@ -2114,7 +2127,7 @@ function generator(context, node) {
|
|
|
2114
2127
|
propertyName: "gen"
|
|
2115
2128
|
}) || node.arguments.length !== 1) return none();
|
|
2116
2129
|
const effect = node.callee.object;
|
|
2117
|
-
return pipe(head(node.arguments), filter((argument) => argument.type === "FunctionExpression" && argument.generator && !argument.async && argument.id === null && isArrayEmpty(argument.params) && argument.body !== null && isNone(match$1(/\b(?:arguments|this)\b/u)(context.sourceCode.getText(argument.body)))), map
|
|
2130
|
+
return pipe(head(node.arguments), filter((argument) => argument.type === "FunctionExpression" && argument.generator && !argument.async && argument.id === null && isArrayEmpty(argument.params) && argument.body !== null && isNone(match$1(/\b(?:arguments|this)\b/u)(context.sourceCode.getText(argument.body)))), map((body) => ({
|
|
2118
2131
|
body,
|
|
2119
2132
|
effect
|
|
2120
2133
|
})));
|
|
@@ -2227,12 +2240,10 @@ function recoversEmpty(context, name, node) {
|
|
|
2227
2240
|
}
|
|
2228
2241
|
const noEmptyRecovery = defineRule({
|
|
2229
2242
|
create: (context) => ({ CallExpression: (node) => {
|
|
2230
|
-
|
|
2243
|
+
const name = pipe(effectMethod({
|
|
2231
2244
|
context,
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
})) return;
|
|
2235
|
-
const name = pipe(memberName(node.callee), getOrElse(() => ""));
|
|
2245
|
+
node
|
|
2246
|
+
}), getOrElse(() => ""));
|
|
2236
2247
|
if (!pipe(name, startsWith("catch")) && !pipe(name, startsWith("orElse"))) return;
|
|
2237
2248
|
for (const argument of node.arguments) {
|
|
2238
2249
|
const callback = resolveBinding(context, argument);
|
|
@@ -2329,17 +2340,16 @@ function inspectPredicate(context, node) {
|
|
|
2329
2340
|
}
|
|
2330
2341
|
const noErrorMessageControlFlow = defineRule({
|
|
2331
2342
|
create: (context) => ({ CallExpression: (node) => {
|
|
2332
|
-
|
|
2343
|
+
const method = effectMethod({
|
|
2333
2344
|
context,
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
if (contains$1(memberName(node.callee), "catchIf")) {
|
|
2345
|
+
node
|
|
2346
|
+
});
|
|
2347
|
+
if (contains$1(method, "catchIf")) {
|
|
2338
2348
|
if (node.arguments.length === 3) inspectPredicate(context, node.arguments[1]);
|
|
2339
2349
|
if (node.arguments.length === 2) inspectPredicate(context, node.arguments[0]);
|
|
2340
2350
|
return;
|
|
2341
2351
|
}
|
|
2342
|
-
if (!contains$1(
|
|
2352
|
+
if (!contains$1(method, "retry")) return;
|
|
2343
2353
|
for (const property of flatMap(node.arguments, (argument) => {
|
|
2344
2354
|
if (argument.type === "ObjectExpression") return argument.properties;
|
|
2345
2355
|
return [];
|
|
@@ -2504,7 +2514,7 @@ function check(input) {
|
|
|
2504
2514
|
}), check({
|
|
2505
2515
|
name: input.name,
|
|
2506
2516
|
node: input.node.right
|
|
2507
|
-
})]), map
|
|
2517
|
+
})]), map(flatten));
|
|
2508
2518
|
if (input.node.type === "UnaryExpression" && input.node.operator === "!" && input.node.argument.type === "CallExpression" && input.node.argument.callee.type === "MemberExpression" && isSubject({
|
|
2509
2519
|
name: "Array",
|
|
2510
2520
|
node: input.node.argument.callee.object
|
|
@@ -2530,7 +2540,7 @@ function check(input) {
|
|
|
2530
2540
|
operator: input.node.operator,
|
|
2531
2541
|
other: input.node.left,
|
|
2532
2542
|
subject: input.node.right
|
|
2533
|
-
})]), map
|
|
2543
|
+
})]), map(of));
|
|
2534
2544
|
}
|
|
2535
2545
|
function replaceableGuard(node) {
|
|
2536
2546
|
const predicate = node.returnType?.typeAnnotation;
|
|
@@ -2539,7 +2549,7 @@ function replaceableGuard(node) {
|
|
|
2539
2549
|
return pipe(check({
|
|
2540
2550
|
name: predicate.parameterName.name,
|
|
2541
2551
|
node: returned
|
|
2542
|
-
}), map
|
|
2552
|
+
}), map((checks) => pipe(checks, sort(Order), join(" && "))), flatMap$1((key) => get$2({
|
|
2543
2553
|
"!= null": "isNotNullish",
|
|
2544
2554
|
"!== null": "isNotNull",
|
|
2545
2555
|
"!== null && !Array.isArray && typeof === object": "isObject",
|
|
@@ -2564,7 +2574,7 @@ function replaceableGuard(node) {
|
|
|
2564
2574
|
}, key)));
|
|
2565
2575
|
}
|
|
2566
2576
|
function report$4(input) {
|
|
2567
|
-
map
|
|
2577
|
+
map(replaceableGuard(input.node), (guard) => input.context.report({
|
|
2568
2578
|
message: `Use Predicate.${guard} instead of this hand-written type guard.`,
|
|
2569
2579
|
node: input.node
|
|
2570
2580
|
}));
|
|
@@ -2637,7 +2647,7 @@ const PRIMITIVES = {
|
|
|
2637
2647
|
const CONTROL_STYLE = /(?:^|:)(?:hover|focus|focus-visible|active):|(?:^|:)(?:rounded|shadow|ring)(?:-|$)|(?:^|:)p[blrtxy]?-(?!0$)|(?:^|:)bg-(?!transparent$)|(?:^|:)border(?:-[blrtxy])?$|(?:^|:)border-(?!0$|[blrtxy]-0$)/u;
|
|
2638
2648
|
function classStrings(node) {
|
|
2639
2649
|
if (node.type === "Literal") return filter$1([node.value], isString);
|
|
2640
|
-
if (node.type === "TemplateLiteral") return map(node.quasis, (quasi) => quasi.value.raw);
|
|
2650
|
+
if (node.type === "TemplateLiteral") return map$1(node.quasis, (quasi) => quasi.value.raw);
|
|
2641
2651
|
if (node.type === "JSXExpressionContainer") return classStrings(node.expression);
|
|
2642
2652
|
if (node.type === "CallExpression") return flatMap(node.arguments, classStrings);
|
|
2643
2653
|
if (node.type === "ConditionalExpression") return flatMap([node.consequent, node.alternate], classStrings);
|
|
@@ -2649,8 +2659,8 @@ const noNativeControl = defineRule({
|
|
|
2649
2659
|
create: (context) => ({ JSXOpeningElement: (node) => {
|
|
2650
2660
|
if (node.name.type !== "JSXIdentifier") return;
|
|
2651
2661
|
const name = node.name.name;
|
|
2652
|
-
map
|
|
2653
|
-
const styled = pipe(node.attributes, findFirst((attribute) => attribute.type === "JSXAttribute" && attribute.name.type === "JSXIdentifier" && attribute.name.name === "className"), map
|
|
2662
|
+
map(get$2(PRIMITIVES, name), (primitive) => {
|
|
2663
|
+
const styled = pipe(node.attributes, findFirst((attribute) => attribute.type === "JSXAttribute" && attribute.name.type === "JSXIdentifier" && attribute.name.name === "className"), map((attribute) => {
|
|
2654
2664
|
if (attribute.type !== "JSXAttribute" || attribute.value === null) return empty$2();
|
|
2655
2665
|
return classStrings(attribute.value);
|
|
2656
2666
|
}), exists((values) => some$1(values, (value) => some$1(split(value, /\s+/u), matches(CONTROL_STYLE)))));
|
|
@@ -2674,7 +2684,7 @@ const noNativeEmptinessCheck = defineRule({
|
|
|
2674
2684
|
context,
|
|
2675
2685
|
node: node.left
|
|
2676
2686
|
})) return;
|
|
2677
|
-
map
|
|
2687
|
+
map(lengthTest(node), (test) => {
|
|
2678
2688
|
context.report({
|
|
2679
2689
|
message: `Use ${PREDICATES[test]}.`,
|
|
2680
2690
|
node
|
|
@@ -2770,10 +2780,10 @@ const noNativeMethodCall = defineRule({
|
|
|
2770
2780
|
"entries",
|
|
2771
2781
|
"keys",
|
|
2772
2782
|
"values"
|
|
2773
|
-
], name) || isArrayEmpty(node.arguments)), flatMap$1((name) => pipe(get$2(REPLACEMENTS, name), map
|
|
2783
|
+
], name) || isArrayEmpty(node.arguments)), flatMap$1((name) => pipe(get$2(REPLACEMENTS, name), map((replacement) => ({
|
|
2774
2784
|
name,
|
|
2775
2785
|
replacement
|
|
2776
|
-
})))), map
|
|
2786
|
+
})))), map((method) => context.report({
|
|
2777
2787
|
message: `Use ${method.replacement} instead of the native .${method.name}(); a third-party object's own method stays, with an inline disable naming it.`,
|
|
2778
2788
|
node: node.callee
|
|
2779
2789
|
})));
|
|
@@ -2900,8 +2910,8 @@ function receiverText(context, node) {
|
|
|
2900
2910
|
function fix$5(input) {
|
|
2901
2911
|
const calls = chain(input.node);
|
|
2902
2912
|
if (!rewritable(input.context, calls)) return [];
|
|
2903
|
-
const steps = filter$1(map(calls, (call) => argumentsText(input.context, call)), (text) => isNonEmpty(text));
|
|
2904
|
-
return getOrElse(flatMap$1(head(calls), (innermost) => map
|
|
2913
|
+
const steps = filter$1(map$1(calls, (call) => argumentsText(input.context, call)), (text) => isNonEmpty(text));
|
|
2914
|
+
return getOrElse(flatMap$1(head(calls), (innermost) => map(effectImport({
|
|
2905
2915
|
context: input.context,
|
|
2906
2916
|
fixer: input.fixer,
|
|
2907
2917
|
name: "pipe",
|
|
@@ -2919,7 +2929,7 @@ const noPipeMethod = defineRule({
|
|
|
2919
2929
|
});
|
|
2920
2930
|
return;
|
|
2921
2931
|
}
|
|
2922
|
-
if (call.parent
|
|
2932
|
+
if (call.parent.type === "MemberExpression" && isNotNullish(call.parent.parent) && pipeCall(call.parent.parent)) {
|
|
2923
2933
|
context.report({
|
|
2924
2934
|
message: MESSAGE$5,
|
|
2925
2935
|
node
|
|
@@ -3043,31 +3053,23 @@ const noPollingTest = defineRule({
|
|
|
3043
3053
|
}
|
|
3044
3054
|
return {
|
|
3045
3055
|
CallExpression: (node) => {
|
|
3046
|
-
|
|
3047
|
-
const callee = node.callee;
|
|
3048
|
-
if (importedMember({
|
|
3056
|
+
const method = effectMethod({
|
|
3049
3057
|
context,
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
})) {
|
|
3058
|
+
node
|
|
3059
|
+
});
|
|
3060
|
+
if (contains$1(method, "eventually")) {
|
|
3054
3061
|
context.report({
|
|
3055
3062
|
message: MESSAGE$4,
|
|
3056
3063
|
node
|
|
3057
3064
|
});
|
|
3058
3065
|
return;
|
|
3059
3066
|
}
|
|
3060
|
-
if (
|
|
3067
|
+
if (exists(method, (name) => contains([
|
|
3061
3068
|
"repeat",
|
|
3062
3069
|
"repeatOrElse",
|
|
3063
3070
|
"retry",
|
|
3064
3071
|
"retryOrElse"
|
|
3065
|
-
],
|
|
3066
|
-
context,
|
|
3067
|
-
importedName: "Effect",
|
|
3068
|
-
node: callee,
|
|
3069
|
-
propertyName
|
|
3070
|
-
})) && (containsNode({
|
|
3072
|
+
], name)) && (containsNode({
|
|
3071
3073
|
context,
|
|
3072
3074
|
matches: (child) => isWait(context, child),
|
|
3073
3075
|
node: pipedFrom(node),
|
|
@@ -3150,7 +3152,7 @@ function enclosed(input) {
|
|
|
3150
3152
|
function needsAlias(input) {
|
|
3151
3153
|
if (input.declaration.parent.type !== "BlockStatement" || !contains(FUNCTIONS, input.declaration.parent.parent.type) || !pipe(input.declaration.parent.body, takeWhile((statement) => statement !== input.declaration), every((statement) => statement.type === "VariableDeclaration"))) return true;
|
|
3152
3154
|
const block = input.declaration.parent;
|
|
3153
|
-
const paths = map(input.reads, (read) => ({
|
|
3155
|
+
const paths = map$1(input.reads, (read) => ({
|
|
3154
3156
|
callback: enclosed({
|
|
3155
3157
|
block,
|
|
3156
3158
|
node: read,
|
|
@@ -3181,7 +3183,7 @@ function replacement(input) {
|
|
|
3181
3183
|
return input.text;
|
|
3182
3184
|
}
|
|
3183
3185
|
function report$3(input) {
|
|
3184
|
-
const reads = pipe(input.variable.references, filter$1((reference) => reference.isRead()), map((reference) => reference.identifier));
|
|
3186
|
+
const reads = pipe(input.variable.references, filter$1((reference) => reference.isRead()), map$1((reference) => reference.identifier));
|
|
3185
3187
|
const text = input.context.sourceCode.getText(input.init);
|
|
3186
3188
|
const aliasRequired = needsAlias({
|
|
3187
3189
|
context: input.context,
|
|
@@ -3232,7 +3234,7 @@ function report$3(input) {
|
|
|
3232
3234
|
node,
|
|
3233
3235
|
read
|
|
3234
3236
|
})) || !every(input.context.sourceCode.getTokensBetween(input.declaration, read), inert$1))) return [];
|
|
3235
|
-
return [fixer.remove(input.declaration), ...map(reads, (read) => fixer.replaceText(read, replacement({
|
|
3237
|
+
return [fixer.remove(input.declaration), ...map$1(reads, (read) => fixer.replaceText(read, replacement({
|
|
3236
3238
|
name: input.name,
|
|
3237
3239
|
read,
|
|
3238
3240
|
text
|
|
@@ -3320,7 +3322,7 @@ const noRedundantStateType = defineRule({
|
|
|
3320
3322
|
propertyName: "make"
|
|
3321
3323
|
})))) return;
|
|
3322
3324
|
if (isString(argument.value) && type?.type === "TSStringKeyword" || isNumber$1(argument.value) && type?.type === "TSNumberKeyword" || isBoolean(argument.value) && type?.type === "TSBooleanKeyword") context.report({
|
|
3323
|
-
fix: (fixer) => toArray$1(map
|
|
3325
|
+
fix: (fixer) => toArray$1(map(fromNullishOr(node.typeArguments), (typeArguments) => fixer.remove(typeArguments))),
|
|
3324
3326
|
message: "Drop this state type; the initializer infers the same primitive type.",
|
|
3325
3327
|
node: type
|
|
3326
3328
|
});
|
|
@@ -3352,7 +3354,7 @@ function nullableType(input) {
|
|
|
3352
3354
|
function removeNull(input) {
|
|
3353
3355
|
const before = input.context.sourceCode.getTokenBefore(input.member);
|
|
3354
3356
|
if (before?.value === "|" && before.range[0] >= input.type.range[0]) return some(input.fixer.removeRange([before.range[0], input.member.range[1]]));
|
|
3355
|
-
return pipe(fromNullishOr(input.context.sourceCode.getTokenAfter(input.member)), filter((token) => token.value === "|"), map
|
|
3357
|
+
return pipe(fromNullishOr(input.context.sourceCode.getTokenAfter(input.member)), filter((token) => token.value === "|"), map((token) => input.fixer.removeRange([input.member.range[0], token.range[1]])));
|
|
3356
3358
|
}
|
|
3357
3359
|
const noRedundantUseRefNullType = defineRule({
|
|
3358
3360
|
create: (context) => ({ CallExpression: (node) => {
|
|
@@ -3389,7 +3391,7 @@ function fix$4(input) {
|
|
|
3389
3391
|
name: "Array",
|
|
3390
3392
|
scope: input.context.sourceCode.getScope(input.init)
|
|
3391
3393
|
}), (variable) => some$1(variable.defs, (definition) => definition.type === "ImportBinding" && definition.parent?.type === "ImportDeclaration" && definition.parent.source.value === "effect"))) return [];
|
|
3392
|
-
return getOrElse(flatMap$1(elementType(input.annotation.typeAnnotation), (element) => map
|
|
3394
|
+
return getOrElse(flatMap$1(elementType(input.annotation.typeAnnotation), (element) => map(effectImport({
|
|
3393
3395
|
context: input.context,
|
|
3394
3396
|
fixer: input.fixer,
|
|
3395
3397
|
name: "Array",
|
|
@@ -3477,7 +3479,7 @@ function shippedSchema(input) {
|
|
|
3477
3479
|
return pipe(shipped, findFirst((entry) => contains$1(base, entry.base) && contains$1(check, entry.check) && isArrayEmpty(rest) && match(fromUndefinedOr(entry.only), {
|
|
3478
3480
|
onNone: () => value === void 0,
|
|
3479
3481
|
onSome: (only) => value?.type === "Literal" && value.value === only
|
|
3480
|
-
})), map
|
|
3482
|
+
})), map((entry) => entry.schema));
|
|
3481
3483
|
}
|
|
3482
3484
|
function pipedBase(node) {
|
|
3483
3485
|
if (node.parent.type !== "CallExpression") return none();
|
|
@@ -3511,7 +3513,7 @@ function reinventedSchema(input) {
|
|
|
3511
3513
|
}
|
|
3512
3514
|
const noReinventedSchema = defineRule({
|
|
3513
3515
|
create: (context) => ({ CallExpression: (node) => {
|
|
3514
|
-
map
|
|
3516
|
+
map(reinventedSchema({
|
|
3515
3517
|
context,
|
|
3516
3518
|
node
|
|
3517
3519
|
}), (schema) => {
|
|
@@ -3548,7 +3550,7 @@ function fix$3(input) {
|
|
|
3548
3550
|
...input,
|
|
3549
3551
|
reference
|
|
3550
3552
|
}))) return none();
|
|
3551
|
-
return some([input.fixer.removeRange([input.node.imported.range[1], input.node.local.range[1]]), ...map(variable.references, (reference) => {
|
|
3553
|
+
return some([input.fixer.removeRange([input.node.imported.range[1], input.node.local.range[1]]), ...map$1(variable.references, (reference) => {
|
|
3552
3554
|
if (reference.identifier.parent.type === "Property" && reference.identifier.parent.shorthand) return input.fixer.replaceText(reference.identifier.parent, `${input.node.local.name}: ${input.imported}`);
|
|
3553
3555
|
return input.fixer.replaceText(reference.identifier, input.imported);
|
|
3554
3556
|
})]);
|
|
@@ -3615,7 +3617,7 @@ function reaches(input) {
|
|
|
3615
3617
|
if (isArrayEmpty(next)) return false;
|
|
3616
3618
|
return reaches({
|
|
3617
3619
|
...input,
|
|
3618
|
-
nodes: pipe(next, flatMap((variable) => variable.defs), filter$1((definition) => definition.type === "FunctionName" || definition.type === "Variable"), map((definition) => definition.node)),
|
|
3620
|
+
nodes: pipe(next, flatMap((variable) => variable.defs), filter$1((definition) => definition.type === "FunctionName" || definition.type === "Variable"), map$1((definition) => definition.node)),
|
|
3619
3621
|
visited: appendAll(input.visited, next)
|
|
3620
3622
|
});
|
|
3621
3623
|
}
|
|
@@ -3718,7 +3720,7 @@ function forwardedChain(input) {
|
|
|
3718
3720
|
});
|
|
3719
3721
|
}
|
|
3720
3722
|
function exactForwardingFunction(input) {
|
|
3721
|
-
const names = pipe(input.node.params, map(parameterName), getSomes);
|
|
3723
|
+
const names = pipe(input.node.params, map$1(parameterName), getSomes);
|
|
3722
3724
|
const returned = returnedExpression(input.node);
|
|
3723
3725
|
if (input.node.async || input.node.generator || isArrayEmpty(names) || names.length !== input.node.params.length || isNullish(returned)) return false;
|
|
3724
3726
|
if (returned.type === "Identifier") return names.length === 1 && returned.name === names[0];
|
|
@@ -3760,14 +3762,15 @@ function copiesSafely(input) {
|
|
|
3760
3762
|
});
|
|
3761
3763
|
}
|
|
3762
3764
|
function singleUseFunction(input) {
|
|
3763
|
-
const names = pipe(input.node.params, map(parameterName), getSomes);
|
|
3765
|
+
const names = pipe(input.node.params, map$1(parameterName), getSomes);
|
|
3764
3766
|
const returned = returnedExpression(input.node);
|
|
3765
3767
|
if (input.node.async || input.node.generator || input.node.typeParameters !== null || input.node.returnType?.typeAnnotation.type === "TSTypePredicate" || isArrayEmpty(names) || names.length !== input.node.params.length || isNullish(returned)) return false;
|
|
3766
3768
|
const oneLine = !pipe(input.context.sourceCode.getText(returned), includes("\n"));
|
|
3767
|
-
return pipe(unexportedBindingName(input.node), flatMap$1((name) =>
|
|
3769
|
+
return pipe(unexportedBindingName(input.node), flatMap$1((name) => readsOf({
|
|
3770
|
+
context: input.context,
|
|
3768
3771
|
name,
|
|
3769
|
-
|
|
3770
|
-
})),
|
|
3772
|
+
node: input.node
|
|
3773
|
+
})), filter((reads) => reads.length === 1), flatMap$1(head), map((reference) => reference.identifier), filter((read) => read.range[0] < input.node.range[0] || read.range[0] > input.node.range[1]), exists((read) => {
|
|
3771
3774
|
if (read.parent.type !== "CallExpression") return false;
|
|
3772
3775
|
if (read.parent.callee !== read) return oneLine && some$1(read.parent.arguments, (argument) => argument === read);
|
|
3773
3776
|
if (!copiesSafely({
|
|
@@ -3791,20 +3794,22 @@ function redundantConstAlias(input) {
|
|
|
3791
3794
|
return definition.node.type === "VariableDeclarator" && definition.node.parent.type === "VariableDeclaration" && definition.node.parent.kind === "const";
|
|
3792
3795
|
});
|
|
3793
3796
|
}))) return false;
|
|
3794
|
-
return pipe(
|
|
3797
|
+
return pipe(readsOf({
|
|
3798
|
+
context: input.context,
|
|
3795
3799
|
name: input.node.id.name,
|
|
3796
|
-
|
|
3797
|
-
}), exists((
|
|
3800
|
+
node: input.node
|
|
3801
|
+
}), exists((reads) => reads.length === 1));
|
|
3798
3802
|
}
|
|
3799
3803
|
function exportedAlias(input) {
|
|
3800
3804
|
return input.node.parent.type === "VariableDeclaration" && input.node.parent.kind === "const" && input.node.parent.parent.type === "ExportNamedDeclaration" && input.node.id.type === "Identifier" && input.node.init?.type === "Identifier" && pipe(variableFor(input.context, input.node.init), exists((variable) => some$1(variable.defs, (definition) => definition.type === "ImportBinding" || definition.type === "FunctionName" || definition.type === "ClassName" || definition.node.type === "VariableDeclarator" && definition.node.parent.type === "VariableDeclaration" && definition.node.parent.kind === "const")));
|
|
3801
3805
|
}
|
|
3802
3806
|
function singleUseLiteral(input) {
|
|
3803
3807
|
if (input.node.parent.type !== "VariableDeclaration" || input.node.parent.kind !== "const" || isExport(input.node.parent.parent) || input.node.parent.parent.type === "Program" || input.node.id.type !== "Identifier" || input.node.id.typeAnnotation !== null || !(input.node.init?.type === "Literal" && !hasProperty(input.node.init, "regex") || input.node.init?.type === "TemplateLiteral" && isArrayEmpty(input.node.init.expressions))) return false;
|
|
3804
|
-
return pipe(
|
|
3808
|
+
return pipe(readsOf({
|
|
3809
|
+
context: input.context,
|
|
3805
3810
|
name: input.node.id.name,
|
|
3806
|
-
|
|
3807
|
-
}),
|
|
3811
|
+
node: input.node
|
|
3812
|
+
}), exists((reads) => reads.length === 1 && reads[0]?.identifier.parent.type !== "ExportSpecifier"));
|
|
3808
3813
|
}
|
|
3809
3814
|
function singleUseLayerPart(input) {
|
|
3810
3815
|
const init = input.node.init;
|
|
@@ -3814,10 +3819,11 @@ function singleUseLayerPart(input) {
|
|
|
3814
3819
|
node: init.callee,
|
|
3815
3820
|
propertyName: "gen"
|
|
3816
3821
|
}))) return false;
|
|
3817
|
-
return pipe(
|
|
3822
|
+
return pipe(readsOf({
|
|
3823
|
+
context: input.context,
|
|
3818
3824
|
name: input.node.id.name,
|
|
3819
|
-
|
|
3820
|
-
}),
|
|
3825
|
+
node: input.node
|
|
3826
|
+
}), exists((reads) => {
|
|
3821
3827
|
const consumer = reads[0]?.identifier.parent;
|
|
3822
3828
|
if (reads.length !== 1 || consumer?.type !== "CallExpression") return false;
|
|
3823
3829
|
if (init.type === "MemberExpression") return importedMember({
|
|
@@ -4057,10 +4063,11 @@ function report$2(input) {
|
|
|
4057
4063
|
if (declaration.type !== "VariableDeclaration" || declaration.parent.type !== "BlockStatement" || input.node.id.type !== "Identifier" || init === null) return;
|
|
4058
4064
|
const statements = declaration.parent.body;
|
|
4059
4065
|
const name = input.node.id.name;
|
|
4060
|
-
pipe(findFirstIndex(statements, (statement) => statement === declaration), flatMap$1((index) => get$3(statements, index + 1)), flatMap$1((next) => pipe(
|
|
4066
|
+
pipe(findFirstIndex(statements, (statement) => statement === declaration), flatMap$1((index) => get$3(statements, index + 1)), flatMap$1((next) => pipe(readsOf({
|
|
4067
|
+
context: input.context,
|
|
4061
4068
|
name,
|
|
4062
|
-
|
|
4063
|
-
}),
|
|
4069
|
+
node: input.node
|
|
4070
|
+
}), filter((reads) => reads.length === 1), flatMap$1(head), map((reference) => reference.identifier), filter((read) => read.range[0] >= next.range[0] && read.range[1] <= next.range[1] && climb({
|
|
4064
4071
|
node: read,
|
|
4065
4072
|
statement: next
|
|
4066
4073
|
}) && readable({
|
|
@@ -4070,7 +4077,7 @@ function report$2(input) {
|
|
|
4070
4077
|
}) && !(init.type === "ConditionalExpression" && insideConditional({
|
|
4071
4078
|
node: read,
|
|
4072
4079
|
statement: next
|
|
4073
|
-
})) && !(suspends(input.context, init) && receiver(outermost(read))) && !some$1(input.effects, (effect) => effect.range[0] >= next.range[0] && effect.range[1] <= read.range[0])), map
|
|
4080
|
+
})) && !(suspends(input.context, init) && receiver(outermost(read))) && !some$1(input.effects, (effect) => effect.range[0] >= next.range[0] && effect.range[1] <= read.range[0])), map((read) => ({
|
|
4074
4081
|
next,
|
|
4075
4082
|
read
|
|
4076
4083
|
})))), match({
|
|
@@ -4139,12 +4146,7 @@ function skips(context, node) {
|
|
|
4139
4146
|
context,
|
|
4140
4147
|
node: chain.root,
|
|
4141
4148
|
source: TEST_RUNNERS
|
|
4142
|
-
}) ||
|
|
4143
|
-
"describe",
|
|
4144
|
-
"it",
|
|
4145
|
-
"suite",
|
|
4146
|
-
"test"
|
|
4147
|
-
], chain.root.name) || hasEffectMember(chain.members));
|
|
4149
|
+
}) || hasEffectMember(chain.members));
|
|
4148
4150
|
}));
|
|
4149
4151
|
}
|
|
4150
4152
|
const noSkippedTest = defineRule({
|
|
@@ -4283,7 +4285,7 @@ function branches(node) {
|
|
|
4283
4285
|
function returns(context, node) {
|
|
4284
4286
|
const chain = branches(node);
|
|
4285
4287
|
if (some$1(chain.tests, (test) => test.consequent.type === "ConditionalExpression")) return [];
|
|
4286
|
-
return [...map(chain.tests, (test) => `if (${context.sourceCode.getText(test.test)}) return ${context.sourceCode.getText(test.consequent)}`), `return ${context.sourceCode.getText(chain.last)}`];
|
|
4288
|
+
return [...map$1(chain.tests, (test) => `if (${context.sourceCode.getText(test.test)}) return ${context.sourceCode.getText(test.consequent)}`), `return ${context.sourceCode.getText(chain.last)}`];
|
|
4287
4289
|
}
|
|
4288
4290
|
function inStatementList(node) {
|
|
4289
4291
|
return node.parent?.type === "BlockStatement" || node.parent?.type === "StaticBlock" || node.parent?.type === "SwitchCase";
|
|
@@ -4483,7 +4485,7 @@ function fix$1(input) {
|
|
|
4483
4485
|
const guard = GUARDS[input.node.parent.right.value];
|
|
4484
4486
|
if (guard === void 0) return [];
|
|
4485
4487
|
const replacement = input.fixer.replaceTextRange(input.node.parent.range, `${NEGATIONS[input.node.parent.operator]}Predicate.${guard}(${input.node.argument.name})`);
|
|
4486
|
-
return getOrElse(map
|
|
4488
|
+
return getOrElse(map(effectImport({
|
|
4487
4489
|
context: input.context,
|
|
4488
4490
|
fixer: input.fixer,
|
|
4489
4491
|
name: "Predicate",
|
|
@@ -4621,7 +4623,7 @@ const WALL_CLOCKS = [
|
|
|
4621
4623
|
function globalPath(context, node) {
|
|
4622
4624
|
if (node.type === "Identifier") return liftPredicate(node.name, () => !exists(variableFor(context, node), (variable) => isArrayNonEmpty(variable.defs)));
|
|
4623
4625
|
if (node.type !== "MemberExpression") return none();
|
|
4624
|
-
return flatMap$1(memberName(node), (name) => map
|
|
4626
|
+
return flatMap$1(memberName(node), (name) => map(globalPath(context, node.object), (path) => `${path}.${name}`));
|
|
4625
4627
|
}
|
|
4626
4628
|
function readsRealTime(context, node) {
|
|
4627
4629
|
if (importedMember({
|
|
@@ -4798,12 +4800,10 @@ function reportOption(context, key, bare, options) {
|
|
|
4798
4800
|
}
|
|
4799
4801
|
const preserveErrorCause = defineRule({
|
|
4800
4802
|
create: (context) => ({ CallExpression: (node) => {
|
|
4801
|
-
|
|
4803
|
+
const name = effectMethod({
|
|
4802
4804
|
context,
|
|
4803
|
-
|
|
4804
|
-
|
|
4805
|
-
})) return;
|
|
4806
|
-
const name = memberName(node.callee);
|
|
4805
|
+
node
|
|
4806
|
+
});
|
|
4807
4807
|
if (contains$1(name, "mapError")) {
|
|
4808
4808
|
const bare = detailedFailure(context, node);
|
|
4809
4809
|
forEach(filter$1(node.arguments, (argument) => dropsCause(context, argument, bare)), (callback) => report$1(context, callback));
|
|
@@ -4997,7 +4997,7 @@ function reportSchemaVariable(input) {
|
|
|
4997
4997
|
name
|
|
4998
4998
|
})) return [];
|
|
4999
4999
|
const start = pipe(input.context.sourceCode.getCommentsBefore(input.statement), head, getOrElse(() => input.statement)).range[0];
|
|
5000
|
-
return [fixer.insertTextBeforeRange([start, start], `${EXPORT_PREFIXES[input.statement.type] ?? ""}type ${name} = typeof ${name}.Type\n`), ...pipe(input.queries, filter$1((query) => contains$1(queriedSchema(query), name) && readsModuleBinding(input.context, query, name)), map((query) => fixer.replaceText(query, name)))];
|
|
5000
|
+
return [fixer.insertTextBeforeRange([start, start], `${EXPORT_PREFIXES[input.statement.type] ?? ""}type ${name} = typeof ${name}.Type\n`), ...pipe(input.queries, filter$1((query) => contains$1(queriedSchema(query), name) && readsModuleBinding(input.context, query, name)), map$1((query) => fixer.replaceText(query, name)))];
|
|
5001
5001
|
},
|
|
5002
5002
|
message: `Place \`type ${name} = typeof ${name}.Type\` immediately before this Schema.`,
|
|
5003
5003
|
node: input.variable
|
|
@@ -5023,7 +5023,7 @@ const schemaTypePair = defineRule({
|
|
|
5023
5023
|
const seeds = make$2();
|
|
5024
5024
|
return {
|
|
5025
5025
|
CallExpression: (node) => {
|
|
5026
|
-
map
|
|
5026
|
+
map(suspendedTypeName({
|
|
5027
5027
|
context,
|
|
5028
5028
|
node
|
|
5029
5029
|
}), (name) => append$1(seeds, name));
|
|
@@ -5098,7 +5098,7 @@ const swiftuiThemeValues = defineRule({
|
|
|
5098
5098
|
const name = calleeName(node);
|
|
5099
5099
|
if (contains(["listRowInsets", "padding"], name) && some$1(properties(node.arguments[0]), (property) => isNumber(property.value)) || name === "lineSpacing" && isNumber(node.arguments[0])) report(context, node, "Space with the theme’s spacing steps, such as padding({all: space[4]}).");
|
|
5100
5100
|
if (name === "font" && some$1(properties(node.arguments[0]), (property) => keyOf(property) === "size")) report(context, node, "Set type with a text token or a Dynamic Type textStyle, not a point size.");
|
|
5101
|
-
if (contains(PAINTS, name) && some$1(flatMap(node.arguments, (argument) => [argument, ...map(properties(argument), (property) => property.value)]), (value) => value.type === "Literal" && isString(value.value) && isSome(match$1(/^#[\da-f]{3,8}$/iu)(value.value)))) report(context, node, "Paint with the theme’s colors, which follow light and dark, not a hex string.");
|
|
5101
|
+
if (contains(PAINTS, name) && some$1(flatMap(node.arguments, (argument) => [argument, ...map$1(properties(argument), (property) => property.value)]), (value) => value.type === "Literal" && isString(value.value) && isSome(match$1(/^#[\da-f]{3,8}$/iu)(value.value)))) report(context, node, "Paint with the theme’s colors, which follow light and dark, not a hex string.");
|
|
5102
5102
|
},
|
|
5103
5103
|
ImportDeclaration: (node) => {
|
|
5104
5104
|
if (startsWith("@expo/ui/swift-ui")(node.source.value)) file.swiftui = true;
|
|
@@ -5294,12 +5294,15 @@ const lint = {
|
|
|
5294
5294
|
{
|
|
5295
5295
|
files: ["**/*.tsx"],
|
|
5296
5296
|
rules: {
|
|
5297
|
+
"effecttsgo/async-function": "off",
|
|
5297
5298
|
"eslint/require-await": "error",
|
|
5299
|
+
"typescript/strict-void-return": "off",
|
|
5298
5300
|
"unicorn/no-null": "off"
|
|
5299
5301
|
}
|
|
5300
5302
|
}
|
|
5301
5303
|
],
|
|
5302
5304
|
plugins: [
|
|
5305
|
+
"effecttsgo",
|
|
5303
5306
|
"eslint",
|
|
5304
5307
|
"typescript",
|
|
5305
5308
|
"oxc",
|
|
@@ -5311,6 +5314,123 @@ const lint = {
|
|
|
5311
5314
|
],
|
|
5312
5315
|
rules: {
|
|
5313
5316
|
...mapEntries(RULES, (_, name) => [`@deslop/coding-standards/${name}`, "error"]),
|
|
5317
|
+
"effecttsgo/any-unknown-in-error-context": "error",
|
|
5318
|
+
"effecttsgo/class-self-mismatch": "error",
|
|
5319
|
+
"effecttsgo/duplicate-package": "error",
|
|
5320
|
+
"effecttsgo/effect-fn-implicit-any": "error",
|
|
5321
|
+
"effecttsgo/error-payload-shadows-name": "error",
|
|
5322
|
+
"effecttsgo/floating-effect": "error",
|
|
5323
|
+
"effecttsgo/floating-effect-in-vitest": "error",
|
|
5324
|
+
"effecttsgo/missing-effect-context": "error",
|
|
5325
|
+
"effecttsgo/missing-effect-error": "error",
|
|
5326
|
+
"effecttsgo/missing-layer-context": "error",
|
|
5327
|
+
"effecttsgo/missing-return-yield-star": "error",
|
|
5328
|
+
"effecttsgo/missing-star-in-yield-effect-gen": "error",
|
|
5329
|
+
"effecttsgo/obsolete-match-import": "error",
|
|
5330
|
+
"effecttsgo/obsolete-schema-import": "error",
|
|
5331
|
+
"effecttsgo/outdated-api": "error",
|
|
5332
|
+
"effecttsgo/overridden-schema-constructor": "error",
|
|
5333
|
+
"effecttsgo/promise-in-effect-success": "error",
|
|
5334
|
+
"effecttsgo/schema-class-object-literal": "error",
|
|
5335
|
+
"effecttsgo/schema-literal-non-finite": "error",
|
|
5336
|
+
"effecttsgo/unsafe-effect-type-assertion": "error",
|
|
5337
|
+
"effecttsgo/catch-unfailable-effect": "error",
|
|
5338
|
+
"effecttsgo/effect-fn-iife": "error",
|
|
5339
|
+
"effecttsgo/effect-gen-uses-adapter": "error",
|
|
5340
|
+
"effecttsgo/effect-in-failure": "error",
|
|
5341
|
+
"effecttsgo/effect-in-void-success": "error",
|
|
5342
|
+
"effecttsgo/effect-try-without-catch": "error",
|
|
5343
|
+
"effecttsgo/global-error-in-effect-catch": "error",
|
|
5344
|
+
"effecttsgo/global-error-in-effect-failure": "error",
|
|
5345
|
+
"effecttsgo/layer-merge-all-with-dependencies": "error",
|
|
5346
|
+
"effecttsgo/lazy-effect": "error",
|
|
5347
|
+
"effecttsgo/lazy-promise-in-effect-sync": "error",
|
|
5348
|
+
"effecttsgo/leaking-requirements": "error",
|
|
5349
|
+
"effecttsgo/multiple-effect-provide": "error",
|
|
5350
|
+
"effecttsgo/return-effect-in-gen": "error",
|
|
5351
|
+
"effecttsgo/schema-sync-in-effect": "error",
|
|
5352
|
+
"effecttsgo/strict-effect-provide": "error",
|
|
5353
|
+
"effecttsgo/try-catch-in-effect-gen": "error",
|
|
5354
|
+
"effecttsgo/async-function": "error",
|
|
5355
|
+
"effecttsgo/global-console": "error",
|
|
5356
|
+
"effecttsgo/global-console-in-effect": "error",
|
|
5357
|
+
"effecttsgo/global-date": "error",
|
|
5358
|
+
"effecttsgo/global-date-in-effect": "error",
|
|
5359
|
+
"effecttsgo/global-fetch": "error",
|
|
5360
|
+
"effecttsgo/global-fetch-in-effect": "error",
|
|
5361
|
+
"effecttsgo/global-json": "error",
|
|
5362
|
+
"effecttsgo/global-json-in-effect": "error",
|
|
5363
|
+
"effecttsgo/global-random": "error",
|
|
5364
|
+
"effecttsgo/global-random-in-effect": "error",
|
|
5365
|
+
"effecttsgo/global-timers": "error",
|
|
5366
|
+
"effecttsgo/global-timers-in-effect": "error",
|
|
5367
|
+
"effecttsgo/instance-of-schema": "error",
|
|
5368
|
+
"effecttsgo/node-builtin-import": "error",
|
|
5369
|
+
"effecttsgo/prefer-effect-array": "error",
|
|
5370
|
+
"effecttsgo/prefer-effect-record": "error",
|
|
5371
|
+
"effecttsgo/prefer-effect-string": "error",
|
|
5372
|
+
"effecttsgo/process-env": "error",
|
|
5373
|
+
"effecttsgo/process-env-in-effect": "error",
|
|
5374
|
+
"effecttsgo/acquire-release-disposable": "error",
|
|
5375
|
+
"effecttsgo/all-of-map-to-for-each": "error",
|
|
5376
|
+
"effecttsgo/catch-all-tag-dispatch-to-catch-tag": "error",
|
|
5377
|
+
"effecttsgo/catch-all-to-map-error": "error",
|
|
5378
|
+
"effecttsgo/catch-chain-to-first-success-of": "error",
|
|
5379
|
+
"effecttsgo/catch-conditional-refail-to-catch-if": "error",
|
|
5380
|
+
"effecttsgo/catch-if-tag-to-catch-tag": "error",
|
|
5381
|
+
"effecttsgo/catch-refail-to-tap-error": "error",
|
|
5382
|
+
"effecttsgo/catch-tag-to-catch-reason": "error",
|
|
5383
|
+
"effecttsgo/catch-to-or-else-succeed": "error",
|
|
5384
|
+
"effecttsgo/deterministic-keys": "error",
|
|
5385
|
+
"effecttsgo/effect-do-notation": "error",
|
|
5386
|
+
"effecttsgo/effect-fn-opportunity": "error",
|
|
5387
|
+
"effecttsgo/effect-map-flatten": "error",
|
|
5388
|
+
"effecttsgo/effect-map-void": "error",
|
|
5389
|
+
"effecttsgo/effect-sleep-zero-to-yield-now": "error",
|
|
5390
|
+
"effecttsgo/effect-succeed-with-undefined": "error",
|
|
5391
|
+
"effecttsgo/effect-succeed-with-void": "error",
|
|
5392
|
+
"effecttsgo/fail-cause-to-constructor": "error",
|
|
5393
|
+
"effecttsgo/flat-map-conditional-to-filter-or-fail": "error",
|
|
5394
|
+
"effecttsgo/flat-map-identity-to-flatten": "error",
|
|
5395
|
+
"effecttsgo/flat-map-ignored-param-to-and-then": "error",
|
|
5396
|
+
"effecttsgo/flat-map-to-map": "error",
|
|
5397
|
+
"effecttsgo/flat-map-to-tap": "error",
|
|
5398
|
+
"effecttsgo/manual-metric-tap-to-track": "error",
|
|
5399
|
+
"effecttsgo/map-const-to-as": "error",
|
|
5400
|
+
"effecttsgo/map-map-error-to-map-both": "error",
|
|
5401
|
+
"effecttsgo/map-some-catch-no-such-element": "error",
|
|
5402
|
+
"effecttsgo/map-some-to-as-some": "error",
|
|
5403
|
+
"effecttsgo/match-boolean-to-is-success": "error",
|
|
5404
|
+
"effecttsgo/match-effect-to-map-both": "error",
|
|
5405
|
+
"effecttsgo/match-effect-to-match": "error",
|
|
5406
|
+
"effecttsgo/match-to-result-or-option": "error",
|
|
5407
|
+
"effecttsgo/multiple-catch-tag": "error",
|
|
5408
|
+
"effecttsgo/nested-effect-gen-yield": "error",
|
|
5409
|
+
"effecttsgo/new-schema-class": "error",
|
|
5410
|
+
"effecttsgo/option-match-to-from-option": "error",
|
|
5411
|
+
"effecttsgo/prefer-schema-type-property": "error",
|
|
5412
|
+
"effecttsgo/prefer-succeed-some-or-none": "error",
|
|
5413
|
+
"effecttsgo/prefer-typed-schema-decoder": "error",
|
|
5414
|
+
"effecttsgo/provide-layer-succeed-to-provide-service": "error",
|
|
5415
|
+
"effecttsgo/provide-merge-all-to-array": "error",
|
|
5416
|
+
"effecttsgo/race-first-with-sleep-to-timeout": "error",
|
|
5417
|
+
"effecttsgo/redundant-map-error": "error",
|
|
5418
|
+
"effecttsgo/redundant-or-die": "error",
|
|
5419
|
+
"effecttsgo/redundant-schema-tag-identifier": "error",
|
|
5420
|
+
"effecttsgo/result-match-to-from-result": "error",
|
|
5421
|
+
"effecttsgo/run-of-exit-to-run-exit": "error",
|
|
5422
|
+
"effecttsgo/schema-number": "error",
|
|
5423
|
+
"effecttsgo/schema-struct-with-tag": "error",
|
|
5424
|
+
"effecttsgo/service-not-as-class": "error",
|
|
5425
|
+
"effecttsgo/suspend-fail-to-fail-sync": "error",
|
|
5426
|
+
"effecttsgo/sync-to-succeed": "error",
|
|
5427
|
+
"effecttsgo/timeout-catch-tag-to-timeout-or-else": "error",
|
|
5428
|
+
"effecttsgo/type-union-to-schema-union": "error",
|
|
5429
|
+
"effecttsgo/unnecessary-effect-gen": "error",
|
|
5430
|
+
"effecttsgo/unnecessary-fail-yieldable-error": "error",
|
|
5431
|
+
"effecttsgo/unnecessary-pipe": "error",
|
|
5432
|
+
"effecttsgo/unnecessary-pipe-chain": "error",
|
|
5433
|
+
"effecttsgo/unnecessary-typeof-type": "error",
|
|
5314
5434
|
"eslint/arrow-body-style": ["error", "as-needed"],
|
|
5315
5435
|
"eslint/constructor-super": "error",
|
|
5316
5436
|
"eslint/curly": [
|
|
@@ -5377,10 +5497,18 @@ const lint = {
|
|
|
5377
5497
|
message: "Import Array from 'effect'.",
|
|
5378
5498
|
name: "Array"
|
|
5379
5499
|
},
|
|
5500
|
+
{
|
|
5501
|
+
message: "Use Base64 or Base64Url from effect/encoding.",
|
|
5502
|
+
name: "atob"
|
|
5503
|
+
},
|
|
5380
5504
|
{
|
|
5381
5505
|
message: "Import Boolean from 'effect'.",
|
|
5382
5506
|
name: "Boolean"
|
|
5383
5507
|
},
|
|
5508
|
+
{
|
|
5509
|
+
message: "Use Base64 or Base64Url from effect/encoding.",
|
|
5510
|
+
name: "btoa"
|
|
5511
|
+
},
|
|
5384
5512
|
{
|
|
5385
5513
|
message: "Use the effect/crypto services: SecureRandom, Digest, Signature.",
|
|
5386
5514
|
name: "crypto"
|
|
@@ -5552,7 +5680,7 @@ const lint = {
|
|
|
5552
5680
|
message: "Use Record or Struct from 'effect'.",
|
|
5553
5681
|
object: "Object"
|
|
5554
5682
|
},
|
|
5555
|
-
...map(RUNNERS, (property) => ({
|
|
5683
|
+
...map$1(RUNNERS, (property) => ({
|
|
5556
5684
|
message: RUN_MESSAGE,
|
|
5557
5685
|
object: "Effect",
|
|
5558
5686
|
property
|
|
@@ -5582,12 +5710,12 @@ const lint = {
|
|
|
5582
5710
|
object: "Math",
|
|
5583
5711
|
property: "round"
|
|
5584
5712
|
},
|
|
5585
|
-
...map(REACT_LEGACY_APIS, (property) => ({
|
|
5713
|
+
...map$1(REACT_LEGACY_APIS, (property) => ({
|
|
5586
5714
|
message: REACT_LEGACY_MESSAGE,
|
|
5587
5715
|
object: "React",
|
|
5588
5716
|
property
|
|
5589
5717
|
})),
|
|
5590
|
-
...map(REACT_HOOKS, (property) => ({
|
|
5718
|
+
...map$1(REACT_HOOKS, (property) => ({
|
|
5591
5719
|
message: `Import ${property} by name from react.`,
|
|
5592
5720
|
object: "React",
|
|
5593
5721
|
property
|
|
@@ -5627,7 +5755,7 @@ const lint = {
|
|
|
5627
5755
|
object: "Data",
|
|
5628
5756
|
property: "TaggedError"
|
|
5629
5757
|
},
|
|
5630
|
-
...map([
|
|
5758
|
+
...map$1([
|
|
5631
5759
|
"addEventListener",
|
|
5632
5760
|
"atob",
|
|
5633
5761
|
"btoa",
|
|
@@ -5647,7 +5775,7 @@ const lint = {
|
|
|
5647
5775
|
object: "window",
|
|
5648
5776
|
property
|
|
5649
5777
|
})),
|
|
5650
|
-
...map([
|
|
5778
|
+
...map$1([
|
|
5651
5779
|
"clearInterval",
|
|
5652
5780
|
"clearTimeout",
|
|
5653
5781
|
"setInterval",
|
|
@@ -5723,7 +5851,6 @@ const lint = {
|
|
|
5723
5851
|
"eslint/no-with": "error",
|
|
5724
5852
|
"eslint/object-shorthand": "error",
|
|
5725
5853
|
"eslint/prefer-arrow-callback": "error",
|
|
5726
|
-
"eslint/prefer-const": ["error", { destructuring: "all" }],
|
|
5727
5854
|
"eslint/prefer-template": "error",
|
|
5728
5855
|
"eslint/preserve-caught-error": "error",
|
|
5729
5856
|
"eslint/require-yield": "error",
|
|
@@ -5935,7 +6062,7 @@ const lint = {
|
|
|
5935
6062
|
"typescript/no-explicit-any": "error",
|
|
5936
6063
|
"typescript/no-extraneous-class": "error",
|
|
5937
6064
|
"typescript/no-import-type-side-effects": "error",
|
|
5938
|
-
"typescript/no-inferrable-types": "error",
|
|
6065
|
+
"typescript/no-inferrable-types": ["error", { ignoreParameters: true }],
|
|
5939
6066
|
"typescript/no-misused-new": "error",
|
|
5940
6067
|
"typescript/no-namespace": ["error", { allowDeclarations: true }],
|
|
5941
6068
|
"typescript/no-non-null-assertion": "error",
|
|
@@ -5962,6 +6089,47 @@ const lint = {
|
|
|
5962
6089
|
"typescript/prefer-function-type": "error",
|
|
5963
6090
|
"typescript/triple-slash-reference": "error",
|
|
5964
6091
|
"typescript/unified-signatures": "error",
|
|
6092
|
+
"typescript/await-thenable": "error",
|
|
6093
|
+
"typescript/consistent-type-exports": "error",
|
|
6094
|
+
"typescript/dot-notation": "error",
|
|
6095
|
+
"typescript/no-array-delete": "error",
|
|
6096
|
+
"typescript/no-base-to-string": "error",
|
|
6097
|
+
"typescript/no-confusing-void-expression": ["error", { ignoreVoidReturningFunctions: true }],
|
|
6098
|
+
"typescript/no-deprecated": "error",
|
|
6099
|
+
"typescript/no-duplicate-type-constituents": "error",
|
|
6100
|
+
"typescript/no-floating-promises": "error",
|
|
6101
|
+
"typescript/no-for-in-array": "error",
|
|
6102
|
+
"typescript/no-generated-empty-object-type": "error",
|
|
6103
|
+
"typescript/no-misused-promises": ["error", { checksVoidReturn: { attributes: false } }],
|
|
6104
|
+
"typescript/no-misused-spread": "error",
|
|
6105
|
+
"typescript/no-redundant-type-constituents": "error",
|
|
6106
|
+
"typescript/no-unnecessary-boolean-literal-compare": "error",
|
|
6107
|
+
"typescript/no-unnecessary-condition": "error",
|
|
6108
|
+
"typescript/no-unnecessary-qualifier": "error",
|
|
6109
|
+
"typescript/no-unnecessary-template-expression": "error",
|
|
6110
|
+
"typescript/no-unnecessary-type-arguments": "error",
|
|
6111
|
+
"typescript/no-unnecessary-type-assertion": "error",
|
|
6112
|
+
"typescript/no-unnecessary-type-conversion": "error",
|
|
6113
|
+
"typescript/no-unnecessary-type-parameters": "error",
|
|
6114
|
+
"typescript/no-unsafe-argument": "error",
|
|
6115
|
+
"typescript/no-unsafe-assignment": "error",
|
|
6116
|
+
"typescript/no-unsafe-call": "error",
|
|
6117
|
+
"typescript/no-unsafe-member-access": "error",
|
|
6118
|
+
"typescript/no-unsafe-return": "error",
|
|
6119
|
+
"typescript/no-unsafe-unary-minus": "error",
|
|
6120
|
+
"typescript/no-useless-default-assignment": "error",
|
|
6121
|
+
"typescript/prefer-nullish-coalescing": ["error", { ignoreTernaryTests: true }],
|
|
6122
|
+
"typescript/prefer-optional-chain": "error",
|
|
6123
|
+
"typescript/restrict-plus-operands": "error",
|
|
6124
|
+
"typescript/restrict-template-expressions": "error",
|
|
6125
|
+
"typescript/strict-boolean-expressions": ["error", {
|
|
6126
|
+
allowNullableObject: false,
|
|
6127
|
+
allowNullableString: true,
|
|
6128
|
+
allowNumber: false,
|
|
6129
|
+
allowString: true
|
|
6130
|
+
}],
|
|
6131
|
+
"typescript/strict-void-return": "error",
|
|
6132
|
+
"typescript/unbound-method": "error",
|
|
5965
6133
|
"unicorn/consistent-function-scoping": "error",
|
|
5966
6134
|
"unicorn/filename-case": "error",
|
|
5967
6135
|
"unicorn/no-abusive-eslint-disable": "error",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deslop/coding-standards",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1244",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/MP281X/deslop.git",
|
|
@@ -36,11 +36,11 @@
|
|
|
36
36
|
"oxlint-plugin-react-doctor": "latest"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
|
+
"@effect/tsgo": ">=0.67",
|
|
39
40
|
"vite-plus": "^1.3"
|
|
40
41
|
},
|
|
41
42
|
"scripts": {
|
|
42
43
|
"build": "vp pack",
|
|
43
|
-
"test": "vp test --config ../../vite.config.ts"
|
|
44
|
-
"typecheck": "tsrs --checkerAssignment go --pretty false"
|
|
44
|
+
"test": "vp test --config ../../vite.config.ts"
|
|
45
45
|
}
|
|
46
46
|
}
|
package/tsconfig.json
CHANGED
|
@@ -24,190 +24,6 @@
|
|
|
24
24
|
"noUncheckedSideEffectImports": true,
|
|
25
25
|
"noEmit": true,
|
|
26
26
|
"incremental": false,
|
|
27
|
-
"plugins": [
|
|
28
|
-
{
|
|
29
|
-
"name": "@effect/language-service",
|
|
30
|
-
"effectFn": ["span", "untraced"],
|
|
31
|
-
"diagnosticSeverity": {
|
|
32
|
-
"abortControllerInEffect": "off",
|
|
33
|
-
"acquireReleaseDisposable": "error",
|
|
34
|
-
"allOfMapToForEach": "error",
|
|
35
|
-
"anyUnknownInErrorContext": "error",
|
|
36
|
-
"apiStabilityLeak": "off",
|
|
37
|
-
"asyncFunction": "error",
|
|
38
|
-
"catchAllTagDispatchToCatchTag": "error",
|
|
39
|
-
"catchAllToMapError": "error",
|
|
40
|
-
"catchChainToFirstSuccessOf": "error",
|
|
41
|
-
"catchConditionalRefailToCatchIf": "error",
|
|
42
|
-
"catchDieToOrDie": "off",
|
|
43
|
-
"catchIfTagToCatchTag": "error",
|
|
44
|
-
"catchRefailToTapError": "error",
|
|
45
|
-
"catchTagToCatchReason": "error",
|
|
46
|
-
"catchToIgnore": "off",
|
|
47
|
-
"catchToOrElseSucceed": "error",
|
|
48
|
-
"catchUnfailableEffect": "error",
|
|
49
|
-
"classSelfMismatch": "error",
|
|
50
|
-
"cryptoRandomUUID": "off",
|
|
51
|
-
"cryptoRandomUUIDInEffect": "off",
|
|
52
|
-
"deterministicKeys": "error",
|
|
53
|
-
"duplicatePackage": "error",
|
|
54
|
-
"effectDoNotation": "error",
|
|
55
|
-
"effectFnIife": "error",
|
|
56
|
-
"effectFnImplicitAny": "error",
|
|
57
|
-
"effectFnOpportunity": "error",
|
|
58
|
-
"effectGenUsesAdapter": "error",
|
|
59
|
-
"effectInFailure": "error",
|
|
60
|
-
"effectInVoidSuccess": "error",
|
|
61
|
-
"effectMapFlatten": "error",
|
|
62
|
-
"effectMapVoid": "error",
|
|
63
|
-
"effectSleepZeroToYieldNow": "error",
|
|
64
|
-
"effectSucceedWithUndefined": "error",
|
|
65
|
-
"effectSucceedWithVoid": "error",
|
|
66
|
-
"effectTryWithoutCatch": "error",
|
|
67
|
-
"errorPayloadShadowsName": "error",
|
|
68
|
-
"experimentalApiUsage": "off",
|
|
69
|
-
"extendsNativeError": "off",
|
|
70
|
-
"failCauseToConstructor": "error",
|
|
71
|
-
"flatMapConditionalToFilterOrFail": "error",
|
|
72
|
-
"flatMapIdentityToFlatten": "error",
|
|
73
|
-
"flatMapIgnoredParamToAndThen": "error",
|
|
74
|
-
"flatMapToMap": "error",
|
|
75
|
-
"flatMapToTap": "error",
|
|
76
|
-
"floatingEffect": "error",
|
|
77
|
-
"floatingEffectInVitest": "error",
|
|
78
|
-
"globalConsole": "error",
|
|
79
|
-
"globalConsoleInEffect": "error",
|
|
80
|
-
"globalDate": "error",
|
|
81
|
-
"globalDateInEffect": "error",
|
|
82
|
-
"globalErrorInEffectCatch": "error",
|
|
83
|
-
"globalErrorInEffectFailure": "error",
|
|
84
|
-
"globalFetch": "error",
|
|
85
|
-
"globalFetchInEffect": "error",
|
|
86
|
-
"globalJson": "error",
|
|
87
|
-
"globalJsonInEffect": "error",
|
|
88
|
-
"globalRandom": "error",
|
|
89
|
-
"globalRandomInEffect": "error",
|
|
90
|
-
"globalTimers": "error",
|
|
91
|
-
"globalTimersInEffect": "error",
|
|
92
|
-
"instanceOfSchema": "error",
|
|
93
|
-
"layerMergeAllWithDependencies": "error",
|
|
94
|
-
"lazyEffect": "error",
|
|
95
|
-
"lazyPromiseInEffectSync": "error",
|
|
96
|
-
"leakingRequirements": "error",
|
|
97
|
-
"manualMetricTapToTrack": "error",
|
|
98
|
-
"mapConstToAs": "error",
|
|
99
|
-
"mapMapErrorToMapBoth": "error",
|
|
100
|
-
"mapSomeCatchNoSuchElement": "error",
|
|
101
|
-
"mapSomeToAsSome": "error",
|
|
102
|
-
"matchBooleanToIsSuccess": "error",
|
|
103
|
-
"matchEffectToMapBoth": "error",
|
|
104
|
-
"matchEffectToMatch": "error",
|
|
105
|
-
"missedPipeableOpportunity": "off",
|
|
106
|
-
"missingEffectContext": "error",
|
|
107
|
-
"missingEffectError": "error",
|
|
108
|
-
"missingLayerContext": "error",
|
|
109
|
-
"missingPipeableSignature": "off",
|
|
110
|
-
"missingReturnYieldStar": "error",
|
|
111
|
-
"missingStarInYieldEffectGen": "error",
|
|
112
|
-
"multipleCatchTag": "error",
|
|
113
|
-
"multipleEffectProvide": "error",
|
|
114
|
-
"nestedEffectGenYield": "error",
|
|
115
|
-
"newPromise": "off",
|
|
116
|
-
"newSchemaClass": "error",
|
|
117
|
-
"nodeBuiltinImport": "error",
|
|
118
|
-
"obsoleteMatchImport": "error",
|
|
119
|
-
"obsoleteSchemaImport": "error",
|
|
120
|
-
"optionMatchToFromOption": "error",
|
|
121
|
-
"outdatedApi": "error",
|
|
122
|
-
"overriddenSchemaConstructor": "error",
|
|
123
|
-
"preferBarrelImport": "off",
|
|
124
|
-
"preferEffectArray": "error",
|
|
125
|
-
"preferEffectRecord": "error",
|
|
126
|
-
"preferEffectString": "error",
|
|
127
|
-
"preferNamespaceImport": "off",
|
|
128
|
-
"preferSchemaTaggedError": "off",
|
|
129
|
-
"preferSchemaTypeProperty": "error",
|
|
130
|
-
"preferSucceedSomeOrNone": "error",
|
|
131
|
-
"preferTypedSchemaDecoder": "error",
|
|
132
|
-
"preferUnsafeConstructor": "off",
|
|
133
|
-
"processEnv": "error",
|
|
134
|
-
"processEnvInEffect": "error",
|
|
135
|
-
"promiseInEffectSuccess": "error",
|
|
136
|
-
"provideLayerSucceedToProvideService": "error",
|
|
137
|
-
"provideMergeAllToArray": "error",
|
|
138
|
-
"raceFirstWithSleepToTimeout": "error",
|
|
139
|
-
"redundantMapError": "error",
|
|
140
|
-
"redundantOrDie": "error",
|
|
141
|
-
"redundantSchemaTagIdentifier": "error",
|
|
142
|
-
"resultMatchToFromResult": "error",
|
|
143
|
-
"returnEffectInGen": "error",
|
|
144
|
-
"runEffectInsideEffect": "off",
|
|
145
|
-
"runOfExitToRunExit": "error",
|
|
146
|
-
"schemaClassMissingBrand": "off",
|
|
147
|
-
"schemaClassObjectLiteral": "error",
|
|
148
|
-
"schemaLiteralNonFinite": "error",
|
|
149
|
-
"schemaNumber": "error",
|
|
150
|
-
"schemaOpaqueInstanceMember": "off",
|
|
151
|
-
"schemaStructWithTag": "error",
|
|
152
|
-
"schemaSync": "off",
|
|
153
|
-
"schemaSyncInEffect": "error",
|
|
154
|
-
"serviceNotAsClass": "error",
|
|
155
|
-
"strictBooleanExpressions": "error",
|
|
156
|
-
"strictEffectProvide": "error",
|
|
157
|
-
"suspendFailToFailSync": "error",
|
|
158
|
-
"syncToSucceed": "error",
|
|
159
|
-
"timeoutCatchTagToTimeoutOrElse": "error",
|
|
160
|
-
"tryCatchInEffectGen": "error",
|
|
161
|
-
"typeUnionToSchemaUnion": "error",
|
|
162
|
-
"unknownInEffectCatch": "off",
|
|
163
|
-
"unnecessaryArrowBlock": "off",
|
|
164
|
-
"unnecessaryEffectGen": "error",
|
|
165
|
-
"unnecessaryFailYieldableError": "error",
|
|
166
|
-
"unnecessaryPipe": "error",
|
|
167
|
-
"unnecessaryPipeChain": "error",
|
|
168
|
-
"unnecessaryTypeofType": "error",
|
|
169
|
-
"unsafeEffectTypeAssertion": "error",
|
|
170
|
-
"unstableApiUsage": "off",
|
|
171
|
-
"unusedDirective": "error",
|
|
172
|
-
// no-single-use-value inlines a single-use yield into its call instead.
|
|
173
|
-
"yieldInCallArgument": "off"
|
|
174
|
-
},
|
|
175
|
-
"ignoreEffectErrorsInTscExitCode": false,
|
|
176
|
-
"ignoreEffectWarningsInTscExitCode": false,
|
|
177
|
-
"ignoreEffectSuggestionsInTscExitCode": false,
|
|
178
|
-
"overrides": [
|
|
179
|
-
{
|
|
180
|
-
// Absolute globs survive extends; the explicit dot component also covers hidden worktrees.
|
|
181
|
-
"include": ["/**/*.tsx", "/**/.*/**/*.tsx"],
|
|
182
|
-
"options": {"diagnosticSeverity": {"asyncFunction": "off"}}
|
|
183
|
-
},
|
|
184
|
-
{
|
|
185
|
-
// shadcn's components stay exactly what its CLI writes, so Effect's style checks do not apply to them.
|
|
186
|
-
"include": [
|
|
187
|
-
"/**/components-web/src/ui/**/*.ts",
|
|
188
|
-
"/**/components-web/src/ui/**/*.tsx",
|
|
189
|
-
"/**/.*/**/components-web/src/ui/**/*.ts",
|
|
190
|
-
"/**/.*/**/components-web/src/ui/**/*.tsx"
|
|
191
|
-
],
|
|
192
|
-
"options": {
|
|
193
|
-
"diagnosticSeverity": {
|
|
194
|
-
"globalRandom": "off",
|
|
195
|
-
"globalTimers": "off",
|
|
196
|
-
"preferEffectArray": "off",
|
|
197
|
-
"preferEffectRecord": "off",
|
|
198
|
-
"preferEffectString": "off",
|
|
199
|
-
"strictBooleanExpressions": "off"
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
},
|
|
203
|
-
{
|
|
204
|
-
// The directive scan reads string literals too, and test fixtures hold source text with directives.
|
|
205
|
-
"include": ["/**/*.test.ts", "/**/.*/**/*.test.ts"],
|
|
206
|
-
"options": {"diagnosticSeverity": {"unusedDirective": "off"}}
|
|
207
|
-
}
|
|
208
|
-
]
|
|
209
|
-
}
|
|
210
|
-
],
|
|
211
27
|
"noUnusedLocals": true,
|
|
212
28
|
"noUnusedParameters": true
|
|
213
29
|
},
|