@venizia/dev-configs 0.4.6 → 0.4.7-1
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/LICENSE.md +1 -3
- package/README.md +1 -1
- package/dist/checks/catalog.d.ts +4 -2
- package/dist/checks/catalog.d.ts.map +1 -1
- package/dist/checks/catalog.js +72 -68
- package/dist/checks/catalog.js.map +1 -1
- package/dist/checks/module-cycles.d.ts +11 -9
- package/dist/checks/module-cycles.d.ts.map +1 -1
- package/dist/checks/module-cycles.js +32 -30
- package/dist/checks/module-cycles.js.map +1 -1
- package/dist/checks/purity/manifest.d.ts +44 -38
- package/dist/checks/purity/manifest.d.ts.map +1 -1
- package/dist/checks/purity/manifest.js +121 -115
- package/dist/checks/purity/manifest.js.map +1 -1
- package/dist/checks/purity/probe.d.ts +22 -18
- package/dist/checks/purity/probe.d.ts.map +1 -1
- package/dist/checks/purity/probe.js +101 -99
- package/dist/checks/purity/probe.js.map +1 -1
- package/dist/checks/purity/run.d.ts +18 -16
- package/dist/checks/purity/run.d.ts.map +1 -1
- package/dist/checks/purity/run.js +90 -86
- package/dist/checks/purity/run.js.map +1 -1
- package/dist/checks/test-controls.d.ts +17 -15
- package/dist/checks/test-controls.d.ts.map +1 -1
- package/dist/checks/test-controls.js +71 -69
- package/dist/checks/test-controls.js.map +1 -1
- package/dist/checks/test-dead-code.d.ts +5 -3
- package/dist/checks/test-dead-code.d.ts.map +1 -1
- package/dist/checks/test-dead-code.js +23 -21
- package/dist/checks/test-dead-code.js.map +1 -1
- package/dist/checks/test-mutate.d.ts +12 -7
- package/dist/checks/test-mutate.d.ts.map +1 -1
- package/dist/checks/test-mutate.js +59 -56
- package/dist/checks/test-mutate.js.map +1 -1
- package/dist/checks/test-weight.d.ts +11 -8
- package/dist/checks/test-weight.d.ts.map +1 -1
- package/dist/checks/test-weight.js +98 -94
- package/dist/checks/test-weight.js.map +1 -1
- package/dist/cli/check.d.ts.map +1 -1
- package/dist/cli/check.js +11 -8
- package/dist/cli/check.js.map +1 -1
- package/dist/cli/codemod/async-style.d.ts +62 -0
- package/dist/cli/codemod/async-style.d.ts.map +1 -0
- package/dist/cli/codemod/async-style.js +248 -0
- package/dist/cli/codemod/async-style.js.map +1 -0
- package/dist/cli/codemod/const-classes.d.ts.map +1 -1
- package/dist/cli/codemod/const-classes.js +2 -1
- package/dist/cli/codemod/const-classes.js.map +1 -1
- package/dist/cli/codemod/drop-redundant-casts.d.ts.map +1 -1
- package/dist/cli/codemod/drop-redundant-casts.js +2 -1
- package/dist/cli/codemod/drop-redundant-casts.js.map +1 -1
- package/dist/cli/codemod/files.d.ts +7 -0
- package/dist/cli/codemod/files.d.ts.map +1 -1
- package/dist/cli/codemod/files.js +33 -0
- package/dist/cli/codemod/files.js.map +1 -1
- package/dist/cli/codemod/index.d.ts.map +1 -1
- package/dist/cli/codemod/index.js +12 -3
- package/dist/cli/codemod/index.js.map +1 -1
- package/dist/cli/codemod/model-settings.d.ts +7 -5
- package/dist/cli/codemod/model-settings.d.ts.map +1 -1
- package/dist/cli/codemod/model-settings.js +293 -291
- package/dist/cli/codemod/model-settings.js.map +1 -1
- package/dist/cli/codemod/namespace-functions/index.d.ts +20 -0
- package/dist/cli/codemod/namespace-functions/index.d.ts.map +1 -0
- package/dist/cli/codemod/namespace-functions/index.js +182 -0
- package/dist/cli/codemod/namespace-functions/index.js.map +1 -0
- package/dist/cli/codemod/namespace-functions/logger-scope.d.ts +32 -0
- package/dist/cli/codemod/namespace-functions/logger-scope.d.ts.map +1 -0
- package/dist/cli/codemod/namespace-functions/logger-scope.js +128 -0
- package/dist/cli/codemod/namespace-functions/logger-scope.js.map +1 -0
- package/dist/cli/codemod/namespace-functions/mapping.d.ts +66 -0
- package/dist/cli/codemod/namespace-functions/mapping.d.ts.map +1 -0
- package/dist/cli/codemod/namespace-functions/mapping.js +99 -0
- package/dist/cli/codemod/namespace-functions/mapping.js.map +1 -0
- package/dist/cli/codemod/namespace-functions/mappings/boot.d.ts +7 -0
- package/dist/cli/codemod/namespace-functions/mappings/boot.d.ts.map +1 -0
- package/dist/cli/codemod/namespace-functions/mappings/boot.js +28 -0
- package/dist/cli/codemod/namespace-functions/mappings/boot.js.map +1 -0
- package/dist/cli/codemod/namespace-functions/mappings/connectors.d.ts +4 -0
- package/dist/cli/codemod/namespace-functions/mappings/connectors.d.ts.map +1 -0
- package/dist/cli/codemod/namespace-functions/mappings/connectors.js +218 -0
- package/dist/cli/codemod/namespace-functions/mappings/connectors.js.map +1 -0
- package/dist/cli/codemod/namespace-functions/mappings/core-server.d.ts +7 -0
- package/dist/cli/codemod/namespace-functions/mappings/core-server.d.ts.map +1 -0
- package/dist/cli/codemod/namespace-functions/mappings/core-server.js +162 -0
- package/dist/cli/codemod/namespace-functions/mappings/core-server.js.map +1 -0
- package/dist/cli/codemod/namespace-functions/mappings/core-worker.d.ts +7 -0
- package/dist/cli/codemod/namespace-functions/mappings/core-worker.d.ts.map +1 -0
- package/dist/cli/codemod/namespace-functions/mappings/core-worker.js +18 -0
- package/dist/cli/codemod/namespace-functions/mappings/core-worker.js.map +1 -0
- package/dist/cli/codemod/namespace-functions/mappings/dev-configs.d.ts +7 -0
- package/dist/cli/codemod/namespace-functions/mappings/dev-configs.d.ts.map +1 -0
- package/dist/cli/codemod/namespace-functions/mappings/dev-configs.js +192 -0
- package/dist/cli/codemod/namespace-functions/mappings/dev-configs.js.map +1 -0
- package/dist/cli/codemod/namespace-functions/mappings/filter.d.ts +7 -0
- package/dist/cli/codemod/namespace-functions/mappings/filter.d.ts.map +1 -0
- package/dist/cli/codemod/namespace-functions/mappings/filter.js +30 -0
- package/dist/cli/codemod/namespace-functions/mappings/filter.js.map +1 -0
- package/dist/cli/codemod/namespace-functions/mappings/helpers.d.ts +16 -0
- package/dist/cli/codemod/namespace-functions/mappings/helpers.d.ts.map +1 -0
- package/dist/cli/codemod/namespace-functions/mappings/helpers.js +535 -0
- package/dist/cli/codemod/namespace-functions/mappings/helpers.js.map +1 -0
- package/dist/cli/codemod/namespace-functions/mappings/index.d.ts +4 -0
- package/dist/cli/codemod/namespace-functions/mappings/index.d.ts.map +1 -0
- package/dist/cli/codemod/namespace-functions/mappings/index.js +25 -0
- package/dist/cli/codemod/namespace-functions/mappings/index.js.map +1 -0
- package/dist/cli/codemod/namespace-functions/mappings/inversion.d.ts +10 -0
- package/dist/cli/codemod/namespace-functions/mappings/inversion.d.ts.map +1 -0
- package/dist/cli/codemod/namespace-functions/mappings/inversion.js +81 -0
- package/dist/cli/codemod/namespace-functions/mappings/inversion.js.map +1 -0
- package/dist/cli/codemod/namespace-functions/mappings/kernel.d.ts +17 -0
- package/dist/cli/codemod/namespace-functions/mappings/kernel.d.ts.map +1 -0
- package/dist/cli/codemod/namespace-functions/mappings/kernel.js +229 -0
- package/dist/cli/codemod/namespace-functions/mappings/kernel.js.map +1 -0
- package/dist/cli/codemod/namespace-functions/rewriter.d.ts +61 -0
- package/dist/cli/codemod/namespace-functions/rewriter.d.ts.map +1 -0
- package/dist/cli/codemod/namespace-functions/rewriter.js +564 -0
- package/dist/cli/codemod/namespace-functions/rewriter.js.map +1 -0
- package/dist/cli/index.js +2 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/compilers/bun.d.ts +1 -1
- package/dist/compilers/bun.js +1 -1
- package/dist/compilers/bun.js.map +1 -1
- package/dist/linters/house/await-support.d.ts +74 -0
- package/dist/linters/house/await-support.d.ts.map +1 -0
- package/dist/linters/house/await-support.js +238 -0
- package/dist/linters/house/await-support.js.map +1 -0
- package/dist/linters/house/common.d.ts +15 -9
- package/dist/linters/house/common.d.ts.map +1 -1
- package/dist/linters/house/common.js +20 -15
- package/dist/linters/house/common.js.map +1 -1
- package/dist/linters/house/configs.d.ts +26 -0
- package/dist/linters/house/configs.d.ts.map +1 -1
- package/dist/linters/house/configs.js +55 -1
- package/dist/linters/house/configs.js.map +1 -1
- package/dist/linters/house/const-class-values.rule.d.ts.map +1 -1
- package/dist/linters/house/const-class-values.rule.js +27 -19
- package/dist/linters/house/const-class-values.rule.js.map +1 -1
- package/dist/linters/house/effect-cleanup-consistency.rule.d.ts +17 -0
- package/dist/linters/house/effect-cleanup-consistency.rule.d.ts.map +1 -0
- package/dist/linters/house/effect-cleanup-consistency.rule.js +87 -0
- package/dist/linters/house/effect-cleanup-consistency.rule.js.map +1 -0
- package/dist/linters/house/hook-support.d.ts +29 -0
- package/dist/linters/house/hook-support.d.ts.map +1 -0
- package/dist/linters/house/hook-support.js +72 -0
- package/dist/linters/house/hook-support.js.map +1 -0
- package/dist/linters/house/index.d.ts +9 -0
- package/dist/linters/house/index.d.ts.map +1 -1
- package/dist/linters/house/index.js +9 -0
- package/dist/linters/house/index.js.map +1 -1
- package/dist/linters/house/max-params-own.rule.d.ts.map +1 -1
- package/dist/linters/house/max-params-own.rule.js +33 -24
- package/dist/linters/house/max-params-own.rule.js.map +1 -1
- package/dist/linters/house/no-async-hook-callback.rule.d.ts +18 -0
- package/dist/linters/house/no-async-hook-callback.rule.d.ts.map +1 -0
- package/dist/linters/house/no-async-hook-callback.rule.js +50 -0
- package/dist/linters/house/no-async-hook-callback.rule.js.map +1 -0
- package/dist/linters/house/no-await-promise-chain.rule.d.ts +24 -0
- package/dist/linters/house/no-await-promise-chain.rule.d.ts.map +1 -0
- package/dist/linters/house/no-await-promise-chain.rule.js +298 -0
- package/dist/linters/house/no-await-promise-chain.rule.js.map +1 -0
- package/dist/linters/house/no-inline-await.rule.d.ts +20 -0
- package/dist/linters/house/no-inline-await.rule.d.ts.map +1 -0
- package/dist/linters/house/no-inline-await.rule.js +70 -0
- package/dist/linters/house/no-inline-await.rule.js.map +1 -0
- package/dist/linters/house/no-new-error.rule.js +4 -4
- package/dist/linters/house/no-new-error.rule.js.map +1 -1
- package/dist/linters/house/no-return-await.rule.d.ts +15 -0
- package/dist/linters/house/no-return-await.rule.d.ts.map +1 -0
- package/dist/linters/house/no-return-await.rule.js +92 -0
- package/dist/linters/house/no-return-await.rule.js.map +1 -0
- package/dist/linters/house/no-silent-catch.rule.d.ts +22 -0
- package/dist/linters/house/no-silent-catch.rule.d.ts.map +1 -0
- package/dist/linters/house/no-silent-catch.rule.js +88 -0
- package/dist/linters/house/no-silent-catch.rule.js.map +1 -0
- package/dist/linters/house/plugin.d.ts.map +1 -1
- package/dist/linters/house/plugin.js +12 -0
- package/dist/linters/house/plugin.js.map +1 -1
- package/dist/linters/house/promise-chain-support.d.ts +49 -0
- package/dist/linters/house/promise-chain-support.d.ts.map +1 -0
- package/dist/linters/house/promise-chain-support.js +188 -0
- package/dist/linters/house/promise-chain-support.js.map +1 -0
- package/dist/linters/rules/no-restricted-properties.rule.js +1 -1
- package/dist/linters/rules/no-restricted-properties.rule.js.map +1 -1
- package/dist/testing/rejection.helper.d.ts +25 -20
- package/dist/testing/rejection.helper.d.ts.map +1 -1
- package/dist/testing/rejection.helper.js +33 -31
- package/dist/testing/rejection.helper.js.map +1 -1
- package/dist/testing/repo-tmp.d.ts +19 -9
- package/dist/testing/repo-tmp.d.ts.map +1 -1
- package/dist/testing/repo-tmp.js +50 -48
- package/dist/testing/repo-tmp.js.map +1 -1
- package/dist/testing/spawn.helper.d.ts +12 -10
- package/dist/testing/spawn.helper.d.ts.map +1 -1
- package/dist/testing/spawn.helper.js +22 -16
- package/dist/testing/spawn.helper.js.map +1 -1
- package/dist/testing/tmpdir-preload.js +1 -1
- package/dist/testing/tmpdir-preload.js.map +1 -1
- package/package.json +2 -3
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.AstNode = exports.HOUSE_PLUGIN_NAMESPACE = exports.AstNodeTypes = void 0;
|
|
4
4
|
/** The estree node types the house rules visit - computed visitor keys, so the names stay PascalCase as ESLint needs them. */
|
|
5
5
|
class AstNodeTypes {
|
|
6
6
|
static { this.NEW_EXPRESSION = 'NewExpression'; }
|
|
@@ -10,22 +10,27 @@ class AstNodeTypes {
|
|
|
10
10
|
static { this.ARROW_FUNCTION_EXPRESSION = 'ArrowFunctionExpression'; }
|
|
11
11
|
static { this.EXPORT_NAMED_DECLARATION = 'ExportNamedDeclaration'; }
|
|
12
12
|
static { this.UNION_TYPE = 'TSUnionType'; }
|
|
13
|
+
static { this.AWAIT_EXPRESSION = 'AwaitExpression'; }
|
|
14
|
+
static { this.RETURN_STATEMENT = 'ReturnStatement'; }
|
|
15
|
+
static { this.CATCH_CLAUSE = 'CatchClause'; }
|
|
13
16
|
}
|
|
14
17
|
exports.AstNodeTypes = AstNodeTypes;
|
|
15
18
|
/** The ESLint namespace the house rules live under: `venizia/<rule>`. */
|
|
16
19
|
exports.HOUSE_PLUGIN_NAMESPACE = 'venizia';
|
|
17
|
-
/**
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
20
|
+
/** Reads an AST node without trusting its type: TypeScript nodes carry fields estree does not declare. */
|
|
21
|
+
class AstNode {
|
|
22
|
+
/** A field of an AST node. */
|
|
23
|
+
static readField(opts) {
|
|
24
|
+
const { node, key } = opts;
|
|
25
|
+
return typeof node === 'object' && node !== null && key in node
|
|
26
|
+
? Reflect.get(node, key)
|
|
27
|
+
: undefined;
|
|
28
|
+
}
|
|
29
|
+
/** The node's `type`, or `undefined` for anything that is not an AST node. */
|
|
30
|
+
static getType(opts) {
|
|
31
|
+
const type = AstNode.readField({ node: opts.node, key: 'type' });
|
|
32
|
+
return typeof type === 'string' ? type : undefined;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
exports.AstNode = AstNode;
|
|
31
36
|
//# sourceMappingURL=common.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"common.js","sourceRoot":"","sources":["../../../src/linters/house/common.ts"],"names":[],"mappings":";;;AAAA,8HAA8H;AAC9H,MAAa,YAAY;aACP,mBAAc,GAAG,eAAe,CAAC;aACjC,oBAAe,GAAG,gBAAgB,CAAC;aACnC,yBAAoB,GAAG,qBAAqB,CAAC;aAC7C,wBAAmB,GAAG,oBAAoB,CAAC;aAC3C,8BAAyB,GAAG,yBAAyB,CAAC;aACtD,6BAAwB,GAAG,wBAAwB,CAAC;aACpD,eAAU,GAAG,aAAa,CAAC;;
|
|
1
|
+
{"version":3,"file":"common.js","sourceRoot":"","sources":["../../../src/linters/house/common.ts"],"names":[],"mappings":";;;AAAA,8HAA8H;AAC9H,MAAa,YAAY;aACP,mBAAc,GAAG,eAAe,CAAC;aACjC,oBAAe,GAAG,gBAAgB,CAAC;aACnC,yBAAoB,GAAG,qBAAqB,CAAC;aAC7C,wBAAmB,GAAG,oBAAoB,CAAC;aAC3C,8BAAyB,GAAG,yBAAyB,CAAC;aACtD,6BAAwB,GAAG,wBAAwB,CAAC;aACpD,eAAU,GAAG,aAAa,CAAC;aAC3B,qBAAgB,GAAG,iBAAiB,CAAC;aACrC,qBAAgB,GAAG,iBAAiB,CAAC;aACrC,iBAAY,GAAG,aAAa,CAAC;;AAV/C,oCAWC;AAED,yEAAyE;AAC5D,QAAA,sBAAsB,GAAG,SAAS,CAAC;AAEhD,0GAA0G;AAC1G,MAAa,OAAO;IAClB,8BAA8B;IAC9B,MAAM,CAAC,SAAS,CAAC,IAAoC;QACnD,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;QAC3B,OAAO,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,IAAI,GAAG,IAAI,IAAI;YAC7D,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC;YACxB,CAAC,CAAC,SAAS,CAAC;IAChB,CAAC;IAED,8EAA8E;IAC9E,MAAM,CAAC,OAAO,CAAC,IAAuB;QACpC,MAAM,IAAI,GAAG,OAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC;QACjE,OAAO,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;IACrD,CAAC;CACF;AAdD,0BAcC","sourcesContent":["/** The estree node types the house rules visit - computed visitor keys, so the names stay PascalCase as ESLint needs them. */\nexport class AstNodeTypes {\n static readonly NEW_EXPRESSION = 'NewExpression';\n static readonly CALL_EXPRESSION = 'CallExpression';\n static readonly FUNCTION_DECLARATION = 'FunctionDeclaration';\n static readonly FUNCTION_EXPRESSION = 'FunctionExpression';\n static readonly ARROW_FUNCTION_EXPRESSION = 'ArrowFunctionExpression';\n static readonly EXPORT_NAMED_DECLARATION = 'ExportNamedDeclaration';\n static readonly UNION_TYPE = 'TSUnionType';\n static readonly AWAIT_EXPRESSION = 'AwaitExpression';\n static readonly RETURN_STATEMENT = 'ReturnStatement';\n static readonly CATCH_CLAUSE = 'CatchClause';\n}\n\n/** The ESLint namespace the house rules live under: `venizia/<rule>`. */\nexport const HOUSE_PLUGIN_NAMESPACE = 'venizia';\n\n/** Reads an AST node without trusting its type: TypeScript nodes carry fields estree does not declare. */\nexport class AstNode {\n /** A field of an AST node. */\n static readField(opts: { node: unknown; key: string }): unknown {\n const { node, key } = opts;\n return typeof node === 'object' && node !== null && key in node\n ? Reflect.get(node, key)\n : undefined;\n }\n\n /** The node's `type`, or `undefined` for anything that is not an AST node. */\n static getType(opts: { node: unknown }): string | undefined {\n const type = AstNode.readField({ node: opts.node, key: 'type' });\n return typeof type === 'string' ? type : undefined;\n }\n}\n"]}
|
|
@@ -13,4 +13,30 @@ import type { Linter } from 'eslint';
|
|
|
13
13
|
export declare const houseConfigs: Linter.Config[];
|
|
14
14
|
/** `houseConfigs` for a React project: `reactNamingConventionConfigs`, the house rules and `no-leaked-render`. */
|
|
15
15
|
export declare const reactHouseConfigs: Linter.Config[];
|
|
16
|
+
/**
|
|
17
|
+
* The async style rules, opt-in until every Venizia repository has been swept (the owner's rollout: the option in
|
|
18
|
+
* one release, the default in the next). Spread it next to `houseConfigs`:
|
|
19
|
+
*
|
|
20
|
+
* ```js
|
|
21
|
+
* export default [...houseConfigs, ...asyncStyleConfigs];
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* `await` stands alone as a statement or as the whole initializer of a declaration (`no-inline-await`), a
|
|
25
|
+
* function returns the promise instead of `return await` (`no-return-await`), an `await` never takes a promise
|
|
26
|
+
* chain (`no-await-promise-chain`), and a caught error leaves a trace (`no-silent-catch`). They apply to test
|
|
27
|
+
* files too.
|
|
28
|
+
*/
|
|
29
|
+
export declare const asyncStyleConfigs: Linter.Config[];
|
|
30
|
+
/**
|
|
31
|
+
* The hook async rules, opt-in like `asyncStyleConfigs`. Spread it next to `reactHouseConfigs`:
|
|
32
|
+
*
|
|
33
|
+
* ```js
|
|
34
|
+
* export default [...reactHouseConfigs, ...reactAsyncStyleConfigs];
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* A hook never gets an async function (`no-async-hook-callback`), and an effect callback returns a cleanup on every
|
|
38
|
+
* path or on none (`effect-cleanup-consistency`). Hooks live in `.ts` files too, so it covers all source files.
|
|
39
|
+
* It also carries `no-await-promise-chain` and `no-silent-catch`: a hook body is where a promise chain lives.
|
|
40
|
+
*/
|
|
41
|
+
export declare const reactAsyncStyleConfigs: Linter.Config[];
|
|
16
42
|
//# sourceMappingURL=configs.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"configs.d.ts","sourceRoot":"","sources":["../../../src/linters/house/configs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"configs.d.ts","sourceRoot":"","sources":["../../../src/linters/house/configs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAwDrC;;;;;;;;;;GAUG;AACH,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,MAAM,EAAsD,CAAC;AAc/F,kHAAkH;AAClH,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAI5C,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAW5C,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,sBAAsB,EAAE,MAAM,CAAC,MAAM,EAWjD,CAAC"}
|
|
@@ -1,14 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.reactHouseConfigs = exports.houseConfigs = void 0;
|
|
3
|
+
exports.reactAsyncStyleConfigs = exports.asyncStyleConfigs = exports.reactHouseConfigs = exports.houseConfigs = void 0;
|
|
4
4
|
const eslint_1 = require("../eslint");
|
|
5
5
|
const jsx_files_1 = require("../jsx-files");
|
|
6
6
|
const react_eslint_1 = require("../react-eslint");
|
|
7
7
|
const common_1 = require("./common");
|
|
8
8
|
const const_class_values_rule_1 = require("./const-class-values.rule");
|
|
9
|
+
const effect_cleanup_consistency_rule_1 = require("./effect-cleanup-consistency.rule");
|
|
9
10
|
const max_params_own_rule_1 = require("./max-params-own.rule");
|
|
11
|
+
const no_async_hook_callback_rule_1 = require("./no-async-hook-callback.rule");
|
|
12
|
+
const no_await_promise_chain_rule_1 = require("./no-await-promise-chain.rule");
|
|
13
|
+
const no_inline_await_rule_1 = require("./no-inline-await.rule");
|
|
10
14
|
const no_leaked_render_rule_1 = require("./no-leaked-render.rule");
|
|
11
15
|
const no_new_error_rule_1 = require("./no-new-error.rule");
|
|
16
|
+
const no_return_await_rule_1 = require("./no-return-await.rule");
|
|
17
|
+
const no_silent_catch_rule_1 = require("./no-silent-catch.rule");
|
|
12
18
|
const plugin_1 = require("./plugin");
|
|
13
19
|
const SOURCE_FILES = ['**/*.{ts,tsx,mts,cts}'];
|
|
14
20
|
const TEST_FILES = ['**/__tests__/**', '**/*.test.{ts,tsx}', '**/*.spec.{ts,tsx}'];
|
|
@@ -75,4 +81,52 @@ exports.reactHouseConfigs = [
|
|
|
75
81
|
...houseRuleConfigs,
|
|
76
82
|
...reactRuleConfigs,
|
|
77
83
|
];
|
|
84
|
+
/**
|
|
85
|
+
* The async style rules, opt-in until every Venizia repository has been swept (the owner's rollout: the option in
|
|
86
|
+
* one release, the default in the next). Spread it next to `houseConfigs`:
|
|
87
|
+
*
|
|
88
|
+
* ```js
|
|
89
|
+
* export default [...houseConfigs, ...asyncStyleConfigs];
|
|
90
|
+
* ```
|
|
91
|
+
*
|
|
92
|
+
* `await` stands alone as a statement or as the whole initializer of a declaration (`no-inline-await`), a
|
|
93
|
+
* function returns the promise instead of `return await` (`no-return-await`), an `await` never takes a promise
|
|
94
|
+
* chain (`no-await-promise-chain`), and a caught error leaves a trace (`no-silent-catch`). They apply to test
|
|
95
|
+
* files too.
|
|
96
|
+
*/
|
|
97
|
+
exports.asyncStyleConfigs = [
|
|
98
|
+
{
|
|
99
|
+
files: SOURCE_FILES,
|
|
100
|
+
plugins: { [common_1.HOUSE_PLUGIN_NAMESPACE]: plugin_1.houseEslintPlugin },
|
|
101
|
+
rules: {
|
|
102
|
+
[no_inline_await_rule_1.NoInlineAwaitRule.NAME]: no_inline_await_rule_1.NoInlineAwaitRule.build(),
|
|
103
|
+
[no_return_await_rule_1.NoReturnAwaitRule.NAME]: no_return_await_rule_1.NoReturnAwaitRule.build(),
|
|
104
|
+
[no_await_promise_chain_rule_1.NoAwaitPromiseChainRule.NAME]: no_await_promise_chain_rule_1.NoAwaitPromiseChainRule.build(),
|
|
105
|
+
[no_silent_catch_rule_1.NoSilentCatchRule.NAME]: no_silent_catch_rule_1.NoSilentCatchRule.build(),
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
];
|
|
109
|
+
/**
|
|
110
|
+
* The hook async rules, opt-in like `asyncStyleConfigs`. Spread it next to `reactHouseConfigs`:
|
|
111
|
+
*
|
|
112
|
+
* ```js
|
|
113
|
+
* export default [...reactHouseConfigs, ...reactAsyncStyleConfigs];
|
|
114
|
+
* ```
|
|
115
|
+
*
|
|
116
|
+
* A hook never gets an async function (`no-async-hook-callback`), and an effect callback returns a cleanup on every
|
|
117
|
+
* path or on none (`effect-cleanup-consistency`). Hooks live in `.ts` files too, so it covers all source files.
|
|
118
|
+
* It also carries `no-await-promise-chain` and `no-silent-catch`: a hook body is where a promise chain lives.
|
|
119
|
+
*/
|
|
120
|
+
exports.reactAsyncStyleConfigs = [
|
|
121
|
+
{
|
|
122
|
+
files: SOURCE_FILES,
|
|
123
|
+
plugins: { [common_1.HOUSE_PLUGIN_NAMESPACE]: plugin_1.houseEslintPlugin },
|
|
124
|
+
rules: {
|
|
125
|
+
[no_async_hook_callback_rule_1.NoAsyncHookCallbackRule.NAME]: no_async_hook_callback_rule_1.NoAsyncHookCallbackRule.build(),
|
|
126
|
+
[effect_cleanup_consistency_rule_1.EffectCleanupConsistencyRule.NAME]: effect_cleanup_consistency_rule_1.EffectCleanupConsistencyRule.build(),
|
|
127
|
+
[no_await_promise_chain_rule_1.NoAwaitPromiseChainRule.NAME]: no_await_promise_chain_rule_1.NoAwaitPromiseChainRule.build(),
|
|
128
|
+
[no_silent_catch_rule_1.NoSilentCatchRule.NAME]: no_silent_catch_rule_1.NoSilentCatchRule.build(),
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
];
|
|
78
132
|
//# sourceMappingURL=configs.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"configs.js","sourceRoot":"","sources":["../../../src/linters/house/configs.ts"],"names":[],"mappings":";;;AACA,sCAAoD;AACpD,4CAAyC;AACzC,kDAA+D;AAC/D,qCAAkD;AAClD,uEAAiE;AACjE,+DAAyD;AACzD,mEAA6D;AAC7D,2DAAqD;AACrD,qCAA6C;AAE7C,MAAM,YAAY,GAAG,CAAC,uBAAuB,CAAC,CAAC;AAC/C,MAAM,UAAU,GAAG,CAAC,iBAAiB,EAAE,oBAAoB,EAAE,oBAAoB,CAAC,CAAC;AAEnF;;;GAGG;AACH,MAAM,YAAY,GAAG,+CAA+C,CAAC;AAErE;;;;;;;;GAQG;AACH,MAAM,gBAAgB,GAAoB;IACxC;QACE,KAAK,EAAE,YAAY;QACnB,OAAO,EAAE,EAAE,CAAC,+BAAsB,CAAC,EAAE,0BAAiB,EAAE;QACxD,KAAK,EAAE;YACL,CAAC,sCAAgB,CAAC,IAAI,CAAC,EAAE,sCAAgB,CAAC,KAAK,EAAE;YACjD,CAAC,kCAAc,CAAC,IAAI,CAAC,EAAE,kCAAc,CAAC,KAAK,EAAE;YAC7C,CAAC,8CAAoB,CAAC,IAAI,CAAC,EAAE,8CAAoB,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;YAC7E,CAAC,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,cAAc,EAAE,OAAO,EAAE,CAAC;SACtD;KACF;IACD;QACE,KAAK,EAAE,UAAU;QACjB,KAAK,EAAE;YACL,CAAC,kCAAc,CAAC,IAAI,CAAC,EAAE,KAAK;YAC5B,CAAC,8CAAoB,CAAC,IAAI,CAAC,EAAE,KAAK;YAClC,CAAC,YAAY,CAAC,EAAE,KAAK;SACtB;KACF;CACF,CAAC;AAEF;;;;;;;;;;GAUG;AACU,QAAA,YAAY,GAAoB,CAAC,GAAG,gCAAuB,EAAE,GAAG,gBAAgB,CAAC,CAAC;AAE/F;;;GAGG;AACH,MAAM,gBAAgB,GAAoB;IACxC;QACE,KAAK,EAAE,qBAAS;QAChB,OAAO,EAAE,EAAE,CAAC,+BAAsB,CAAC,EAAE,0BAAiB,EAAE;QACxD,KAAK,EAAE,EAAE,CAAC,0CAAkB,CAAC,IAAI,CAAC,EAAE,0CAAkB,CAAC,KAAK,EAAE,EAAE;KACjE;CACF,CAAC;AAEF,kHAAkH;AACrG,QAAA,iBAAiB,GAAoB;IAChD,GAAG,2CAA4B;IAC/B,GAAG,gBAAgB;IACnB,GAAG,gBAAgB;CACpB,CAAC","sourcesContent":["import type { Linter } from 'eslint';\nimport { namingConventionConfigs } from '../eslint';\nimport { JSX_FILES } from '../jsx-files';\nimport { reactNamingConventionConfigs } from '../react-eslint';\nimport { HOUSE_PLUGIN_NAMESPACE } from './common';\nimport { ConstClassValuesRule } from './const-class-values.rule';\nimport { MaxParamsOwnRule } from './max-params-own.rule';\nimport { NoLeakedRenderRule } from './no-leaked-render.rule';\nimport { NoNewErrorRule } from './no-new-error.rule';\nimport { houseEslintPlugin } from './plugin';\n\nconst SOURCE_FILES = ['**/*.{ts,tsx,mts,cts}'];\nconst TEST_FILES = ['**/__tests__/**', '**/*.test.{ts,tsx}', '**/*.spec.{ts,tsx}'];\n\n/**\n * V-C-10: no explicit cast. `as const` is always allowed; `satisfies`, a generic or a narrower type\n * replaces the rest.\n */\nconst NO_CAST_RULE = '@typescript-eslint/consistent-type-assertions';\n\n/**\n * The house rules: at most 5 positional parameters on a function we write, and errors thrown through\n * `getError` only. Tests are exempt from `no-new-error`: a test throws a plain `Error` on purpose, to\n * stand in for what a driver or a third-party library throws.\n *\n * Two rules only warn, so a project adopts them without failing its lint: `const-class-values` (V-C-08, a\n * string-literal union in an exported declaration) and `consistent-type-assertions` (V-C-10, an `as X`\n * cast). Tests are exempt from both: a test stubs what it does not build.\n */\nconst houseRuleConfigs: Linter.Config[] = [\n {\n files: SOURCE_FILES,\n plugins: { [HOUSE_PLUGIN_NAMESPACE]: houseEslintPlugin },\n rules: {\n [MaxParamsOwnRule.NAME]: MaxParamsOwnRule.build(),\n [NoNewErrorRule.NAME]: NoNewErrorRule.build(),\n [ConstClassValuesRule.NAME]: ConstClassValuesRule.build({ severity: 'warn' }),\n [NO_CAST_RULE]: ['warn', { assertionStyle: 'never' }],\n },\n },\n {\n files: TEST_FILES,\n rules: {\n [NoNewErrorRule.NAME]: 'off',\n [ConstClassValuesRule.NAME]: 'off',\n [NO_CAST_RULE]: 'off',\n },\n },\n];\n\n/**\n * The ESLint side of a project that lints with oxlint: the naming convention plus the house rules -\n * everything oxlint cannot express. Run it next to `oxlintConfigs`.\n *\n * ```js\n * // .configs/lints/eslint.config.mjs\n * import { houseConfigs } from '@venizia/dev-configs/linters';\n *\n * export default houseConfigs;\n * ```\n */\nexport const houseConfigs: Linter.Config[] = [...namingConventionConfigs, ...houseRuleConfigs];\n\n/**\n * The React house rule: a JSX child is drawn with `cond ? <X /> : null`, never `cond && <X />`, which\n * draws `0` when `cond` is `0`.\n */\nconst reactRuleConfigs: Linter.Config[] = [\n {\n files: JSX_FILES,\n plugins: { [HOUSE_PLUGIN_NAMESPACE]: houseEslintPlugin },\n rules: { [NoLeakedRenderRule.NAME]: NoLeakedRenderRule.build() },\n },\n];\n\n/** `houseConfigs` for a React project: `reactNamingConventionConfigs`, the house rules and `no-leaked-render`. */\nexport const reactHouseConfigs: Linter.Config[] = [\n ...reactNamingConventionConfigs,\n ...houseRuleConfigs,\n ...reactRuleConfigs,\n];\n"]}
|
|
1
|
+
{"version":3,"file":"configs.js","sourceRoot":"","sources":["../../../src/linters/house/configs.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Linter } from 'eslint';\nimport { namingConventionConfigs } from '../eslint';\nimport { JSX_FILES } from '../jsx-files';\nimport { reactNamingConventionConfigs } from '../react-eslint';\nimport { HOUSE_PLUGIN_NAMESPACE } from './common';\nimport { ConstClassValuesRule } from './const-class-values.rule';\nimport { EffectCleanupConsistencyRule } from './effect-cleanup-consistency.rule';\nimport { MaxParamsOwnRule } from './max-params-own.rule';\nimport { NoAsyncHookCallbackRule } from './no-async-hook-callback.rule';\nimport { NoAwaitPromiseChainRule } from './no-await-promise-chain.rule';\nimport { NoInlineAwaitRule } from './no-inline-await.rule';\nimport { NoLeakedRenderRule } from './no-leaked-render.rule';\nimport { NoNewErrorRule } from './no-new-error.rule';\nimport { NoReturnAwaitRule } from './no-return-await.rule';\nimport { NoSilentCatchRule } from './no-silent-catch.rule';\nimport { houseEslintPlugin } from './plugin';\n\nconst SOURCE_FILES = ['**/*.{ts,tsx,mts,cts}'];\nconst TEST_FILES = ['**/__tests__/**', '**/*.test.{ts,tsx}', '**/*.spec.{ts,tsx}'];\n\n/**\n * V-C-10: no explicit cast. `as const` is always allowed; `satisfies`, a generic or a narrower type\n * replaces the rest.\n */\nconst NO_CAST_RULE = '@typescript-eslint/consistent-type-assertions';\n\n/**\n * The house rules: at most 5 positional parameters on a function we write, and errors thrown through\n * `getError` only. Tests are exempt from `no-new-error`: a test throws a plain `Error` on purpose, to\n * stand in for what a driver or a third-party library throws.\n *\n * Two rules only warn, so a project adopts them without failing its lint: `const-class-values` (V-C-08, a\n * string-literal union in an exported declaration) and `consistent-type-assertions` (V-C-10, an `as X`\n * cast). Tests are exempt from both: a test stubs what it does not build.\n */\nconst houseRuleConfigs: Linter.Config[] = [\n {\n files: SOURCE_FILES,\n plugins: { [HOUSE_PLUGIN_NAMESPACE]: houseEslintPlugin },\n rules: {\n [MaxParamsOwnRule.NAME]: MaxParamsOwnRule.build(),\n [NoNewErrorRule.NAME]: NoNewErrorRule.build(),\n [ConstClassValuesRule.NAME]: ConstClassValuesRule.build({ severity: 'warn' }),\n [NO_CAST_RULE]: ['warn', { assertionStyle: 'never' }],\n },\n },\n {\n files: TEST_FILES,\n rules: {\n [NoNewErrorRule.NAME]: 'off',\n [ConstClassValuesRule.NAME]: 'off',\n [NO_CAST_RULE]: 'off',\n },\n },\n];\n\n/**\n * The ESLint side of a project that lints with oxlint: the naming convention plus the house rules -\n * everything oxlint cannot express. Run it next to `oxlintConfigs`.\n *\n * ```js\n * // .configs/lints/eslint.config.mjs\n * import { houseConfigs } from '@venizia/dev-configs/linters';\n *\n * export default houseConfigs;\n * ```\n */\nexport const houseConfigs: Linter.Config[] = [...namingConventionConfigs, ...houseRuleConfigs];\n\n/**\n * The React house rule: a JSX child is drawn with `cond ? <X /> : null`, never `cond && <X />`, which\n * draws `0` when `cond` is `0`.\n */\nconst reactRuleConfigs: Linter.Config[] = [\n {\n files: JSX_FILES,\n plugins: { [HOUSE_PLUGIN_NAMESPACE]: houseEslintPlugin },\n rules: { [NoLeakedRenderRule.NAME]: NoLeakedRenderRule.build() },\n },\n];\n\n/** `houseConfigs` for a React project: `reactNamingConventionConfigs`, the house rules and `no-leaked-render`. */\nexport const reactHouseConfigs: Linter.Config[] = [\n ...reactNamingConventionConfigs,\n ...houseRuleConfigs,\n ...reactRuleConfigs,\n];\n\n/**\n * The async style rules, opt-in until every Venizia repository has been swept (the owner's rollout: the option in\n * one release, the default in the next). Spread it next to `houseConfigs`:\n *\n * ```js\n * export default [...houseConfigs, ...asyncStyleConfigs];\n * ```\n *\n * `await` stands alone as a statement or as the whole initializer of a declaration (`no-inline-await`), a\n * function returns the promise instead of `return await` (`no-return-await`), an `await` never takes a promise\n * chain (`no-await-promise-chain`), and a caught error leaves a trace (`no-silent-catch`). They apply to test\n * files too.\n */\nexport const asyncStyleConfigs: Linter.Config[] = [\n {\n files: SOURCE_FILES,\n plugins: { [HOUSE_PLUGIN_NAMESPACE]: houseEslintPlugin },\n rules: {\n [NoInlineAwaitRule.NAME]: NoInlineAwaitRule.build(),\n [NoReturnAwaitRule.NAME]: NoReturnAwaitRule.build(),\n [NoAwaitPromiseChainRule.NAME]: NoAwaitPromiseChainRule.build(),\n [NoSilentCatchRule.NAME]: NoSilentCatchRule.build(),\n },\n },\n];\n\n/**\n * The hook async rules, opt-in like `asyncStyleConfigs`. Spread it next to `reactHouseConfigs`:\n *\n * ```js\n * export default [...reactHouseConfigs, ...reactAsyncStyleConfigs];\n * ```\n *\n * A hook never gets an async function (`no-async-hook-callback`), and an effect callback returns a cleanup on every\n * path or on none (`effect-cleanup-consistency`). Hooks live in `.ts` files too, so it covers all source files.\n * It also carries `no-await-promise-chain` and `no-silent-catch`: a hook body is where a promise chain lives.\n */\nexport const reactAsyncStyleConfigs: Linter.Config[] = [\n {\n files: SOURCE_FILES,\n plugins: { [HOUSE_PLUGIN_NAMESPACE]: houseEslintPlugin },\n rules: {\n [NoAsyncHookCallbackRule.NAME]: NoAsyncHookCallbackRule.build(),\n [EffectCleanupConsistencyRule.NAME]: EffectCleanupConsistencyRule.build(),\n [NoAwaitPromiseChainRule.NAME]: NoAwaitPromiseChainRule.build(),\n [NoSilentCatchRule.NAME]: NoSilentCatchRule.build(),\n },\n },\n];\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"const-class-values.rule.d.ts","sourceRoot":"","sources":["../../../src/linters/house/const-class-values.rule.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC3C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"const-class-values.rule.d.ts","sourceRoot":"","sources":["../../../src/linters/house/const-class-values.rule.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC3C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AA2DrD;;;;;;;;;GASG;AACH,qBAAa,oBAAoB;IAC/B,MAAM,CAAC,QAAQ,CAAC,IAAI,gCAAkD;IAEtE,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,UAAU,CAyDnC;IAEF,MAAM,CAAC,KAAK,CAAC,IAAI,GAAE;QAAE,QAAQ,CAAC,EAAE,aAAa,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,MAAM,CAAC,SAAS;CAI9F"}
|
|
@@ -6,23 +6,26 @@ const common_1 = require("./common");
|
|
|
6
6
|
const KEY_SET_TYPES = new Set(['Pick', 'Omit', 'Extract', 'Exclude', 'Record']);
|
|
7
7
|
/** The union is a type argument of a key-set utility type, or the key range of a mapped type. */
|
|
8
8
|
const isKeySet = (opts) => {
|
|
9
|
-
const parent =
|
|
10
|
-
if (
|
|
9
|
+
const parent = common_1.AstNode.readField({ node: opts.node, key: 'parent' });
|
|
10
|
+
if (common_1.AstNode.getType({ node: parent }) === 'TSMappedType') {
|
|
11
11
|
return true;
|
|
12
12
|
}
|
|
13
|
-
if (
|
|
13
|
+
if (common_1.AstNode.getType({ node: parent }) !== 'TSTypeParameterInstantiation') {
|
|
14
14
|
return false;
|
|
15
15
|
}
|
|
16
|
-
const reference =
|
|
17
|
-
const name =
|
|
18
|
-
|
|
16
|
+
const reference = common_1.AstNode.readField({ node: parent, key: 'parent' });
|
|
17
|
+
const name = common_1.AstNode.readField({
|
|
18
|
+
node: common_1.AstNode.readField({ node: reference, key: 'typeName' }),
|
|
19
|
+
key: 'name',
|
|
20
|
+
});
|
|
21
|
+
return (common_1.AstNode.getType({ node: reference }) === 'TSTypeReference' && KEY_SET_TYPES.has(String(name)));
|
|
19
22
|
};
|
|
20
23
|
/** The statement of the module that holds the node: the node's last ancestor before `Program`. */
|
|
21
24
|
const topLevelStatement = (opts) => {
|
|
22
25
|
let current = opts.node;
|
|
23
26
|
while (current) {
|
|
24
|
-
const parent =
|
|
25
|
-
if (
|
|
27
|
+
const parent = common_1.AstNode.readField({ node: current, key: 'parent' });
|
|
28
|
+
if (common_1.AstNode.getType({ node: parent }) === 'Program') {
|
|
26
29
|
return current;
|
|
27
30
|
}
|
|
28
31
|
current = parent;
|
|
@@ -31,12 +34,14 @@ const topLevelStatement = (opts) => {
|
|
|
31
34
|
};
|
|
32
35
|
const isStringLiteral = (opts) => {
|
|
33
36
|
const { member } = opts;
|
|
34
|
-
return (
|
|
35
|
-
typeof
|
|
36
|
-
'
|
|
37
|
+
return (common_1.AstNode.getType({ node: member }) === 'TSLiteralType' &&
|
|
38
|
+
typeof common_1.AstNode.readField({
|
|
39
|
+
node: common_1.AstNode.readField({ node: member, key: 'literal' }),
|
|
40
|
+
key: 'value',
|
|
41
|
+
}) === 'string');
|
|
37
42
|
};
|
|
38
43
|
const isNullish = (opts) => {
|
|
39
|
-
const type =
|
|
44
|
+
const type = common_1.AstNode.getType({ node: opts.member });
|
|
40
45
|
return type === 'TSNullKeyword' || type === 'TSUndefinedKeyword';
|
|
41
46
|
};
|
|
42
47
|
/**
|
|
@@ -61,21 +66,24 @@ class ConstClassValuesRule {
|
|
|
61
66
|
},
|
|
62
67
|
create: (context) => {
|
|
63
68
|
const options = context.options[0];
|
|
64
|
-
const configured =
|
|
69
|
+
const configured = common_1.AstNode.readField({ node: options, key: 'namePattern' });
|
|
65
70
|
const namePattern = typeof configured === 'string' ? new RegExp(configured) : undefined;
|
|
66
71
|
const isNamed = (opts) => {
|
|
67
72
|
const { statement, node } = opts;
|
|
68
|
-
const declaration =
|
|
69
|
-
const name =
|
|
73
|
+
const declaration = common_1.AstNode.readField({ node: statement, key: 'declaration' });
|
|
74
|
+
const name = common_1.AstNode.readField({
|
|
75
|
+
node: common_1.AstNode.readField({ node: declaration, key: 'id' }),
|
|
76
|
+
key: 'name',
|
|
77
|
+
});
|
|
70
78
|
return (namePattern === undefined ||
|
|
71
|
-
(
|
|
72
|
-
|
|
79
|
+
(common_1.AstNode.getType({ node: declaration }) === 'TSTypeAliasDeclaration' &&
|
|
80
|
+
common_1.AstNode.readField({ node: declaration, key: 'typeAnnotation' }) === node &&
|
|
73
81
|
typeof name === 'string' &&
|
|
74
82
|
namePattern.test(name)));
|
|
75
83
|
};
|
|
76
84
|
return {
|
|
77
85
|
[common_1.AstNodeTypes.UNION_TYPE]: (node) => {
|
|
78
|
-
const members =
|
|
86
|
+
const members = common_1.AstNode.readField({ node, key: 'types' });
|
|
79
87
|
if (!Array.isArray(members)) {
|
|
80
88
|
return;
|
|
81
89
|
}
|
|
@@ -84,7 +92,7 @@ class ConstClassValuesRule {
|
|
|
84
92
|
return;
|
|
85
93
|
}
|
|
86
94
|
const statement = topLevelStatement({ node });
|
|
87
|
-
const statementType =
|
|
95
|
+
const statementType = common_1.AstNode.getType({ node: statement });
|
|
88
96
|
const isExported = statementType === common_1.AstNodeTypes.EXPORT_NAMED_DECLARATION ||
|
|
89
97
|
statementType === 'ExportDefaultDeclaration';
|
|
90
98
|
if (!isExported || isKeySet({ node }) || !isNamed({ statement, node })) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"const-class-values.rule.js","sourceRoot":"","sources":["../../../src/linters/house/const-class-values.rule.ts"],"names":[],"mappings":";;;AAEA,
|
|
1
|
+
{"version":3,"file":"const-class-values.rule.js","sourceRoot":"","sources":["../../../src/linters/house/const-class-values.rule.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Linter, Rule } from 'eslint';\nimport type { TRuleSeverity } from '../rules/common';\nimport { AstNode, AstNodeTypes, HOUSE_PLUGIN_NAMESPACE } from './common';\n\n/** Utility types whose type argument is a set of keys, not an enumerable value: `Pick<T, 'a' | 'b'>`. */\nconst KEY_SET_TYPES = new Set(['Pick', 'Omit', 'Extract', 'Exclude', 'Record']);\n\n/** The union is a type argument of a key-set utility type, or the key range of a mapped type. */\nconst isKeySet = (opts: { node: unknown }): boolean => {\n const parent = AstNode.readField({ node: opts.node, key: 'parent' });\n\n if (AstNode.getType({ node: parent }) === 'TSMappedType') {\n return true;\n }\n\n if (AstNode.getType({ node: parent }) !== 'TSTypeParameterInstantiation') {\n return false;\n }\n\n const reference = AstNode.readField({ node: parent, key: 'parent' });\n const name = AstNode.readField({\n node: AstNode.readField({ node: reference, key: 'typeName' }),\n key: 'name',\n });\n return (\n AstNode.getType({ node: reference }) === 'TSTypeReference' && KEY_SET_TYPES.has(String(name))\n );\n};\n\n/** The statement of the module that holds the node: the node's last ancestor before `Program`. */\nconst topLevelStatement = (opts: { node: unknown }): unknown => {\n let current = opts.node;\n\n while (current) {\n const parent = AstNode.readField({ node: current, key: 'parent' });\n if (AstNode.getType({ node: parent }) === 'Program') {\n return current;\n }\n current = parent;\n }\n\n return undefined;\n};\n\nconst isStringLiteral = (opts: { member: unknown }): boolean => {\n const { member } = opts;\n return (\n AstNode.getType({ node: member }) === 'TSLiteralType' &&\n typeof AstNode.readField({\n node: AstNode.readField({ node: member, key: 'literal' }),\n key: 'value',\n }) === 'string'\n );\n};\n\nconst isNullish = (opts: { member: unknown }): boolean => {\n const type = AstNode.getType({ node: opts.member });\n return type === 'TSNullKeyword' || type === 'TSUndefinedKeyword';\n};\n\n/**\n * `venizia/const-class-values`. An enumerable string is a const class plus `TConstValue<typeof X>`,\n * never a union of string literals in an exported declaration: a type alias, an interface member, a\n * generic constraint, a parameter or a return type of an exported function or class.\n *\n * Not counted: a union that is not all string literals (a `null` or `undefined` member is ignored),\n * a key set (`Pick`, `Omit`, `Extract`, `Exclude`, `Record` arguments and mapped-type keys), and a\n * declaration that is not exported. `namePattern` narrows the rule to exported type aliases whose name\n * matches it (`(State|Status)$`), for a project that adopts the rule one name at a time.\n */\nexport class ConstClassValuesRule {\n static readonly NAME = `${HOUSE_PLUGIN_NAMESPACE}/const-class-values`;\n\n static readonly RULE: Rule.RuleModule = {\n meta: {\n type: 'suggestion',\n schema: [{ type: 'object', properties: { namePattern: { type: 'string' } } }],\n messages: {\n constClass:\n 'An enumerable string is a const class plus TConstValue<typeof X>, not a union of string literals.',\n },\n },\n create: (context) => {\n const options: unknown = context.options[0];\n const configured = AstNode.readField({ node: options, key: 'namePattern' });\n const namePattern = typeof configured === 'string' ? new RegExp(configured) : undefined;\n\n const isNamed = (opts: { statement: unknown; node: unknown }) => {\n const { statement, node } = opts;\n const declaration = AstNode.readField({ node: statement, key: 'declaration' });\n const name = AstNode.readField({\n node: AstNode.readField({ node: declaration, key: 'id' }),\n key: 'name',\n });\n\n return (\n namePattern === undefined ||\n (AstNode.getType({ node: declaration }) === 'TSTypeAliasDeclaration' &&\n AstNode.readField({ node: declaration, key: 'typeAnnotation' }) === node &&\n typeof name === 'string' &&\n namePattern.test(name))\n );\n };\n\n return {\n [AstNodeTypes.UNION_TYPE]: (node: Rule.Node) => {\n const members = AstNode.readField({ node, key: 'types' });\n if (!Array.isArray(members)) {\n return;\n }\n\n const values = members.filter((member) => !isNullish({ member }));\n if (values.length < 2 || !values.every((member) => isStringLiteral({ member }))) {\n return;\n }\n\n const statement = topLevelStatement({ node });\n const statementType = AstNode.getType({ node: statement });\n const isExported =\n statementType === AstNodeTypes.EXPORT_NAMED_DECLARATION ||\n statementType === 'ExportDefaultDeclaration';\n\n if (!isExported || isKeySet({ node }) || !isNamed({ statement, node })) {\n return;\n }\n\n context.report({ node, messageId: 'constClass' });\n },\n };\n },\n };\n\n static build(opts: { severity?: TRuleSeverity; namePattern?: string } = {}): Linter.RuleEntry {\n const { severity = 'error', namePattern } = opts;\n return namePattern === undefined ? [severity] : [severity, { namePattern }];\n }\n}\n"]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Rule } from 'eslint';
|
|
2
|
+
import type { TRuleSeverity } from '../rules/common';
|
|
3
|
+
/**
|
|
4
|
+
* `venizia/effect-cleanup-consistency`. The callback of `useEffect`, `useLayoutEffect` and `useInsertionEffect`
|
|
5
|
+
* returns a cleanup on every path or on none. An early `return;` beside a later `return () => {}` leaves React
|
|
6
|
+
* with a cleanup on some runs only; the early exit returns a no-op instead. A bare `return;` and falling off the
|
|
7
|
+
* end both mean "no value". It uses ESLint's code path analysis the way `consistent-return` does, so an
|
|
8
|
+
* unreachable end of the function is not a path. A nested function's own `return` is not counted.
|
|
9
|
+
*/
|
|
10
|
+
export declare class EffectCleanupConsistencyRule {
|
|
11
|
+
static readonly NAME = "venizia/effect-cleanup-consistency";
|
|
12
|
+
static readonly RULE: Rule.RuleModule;
|
|
13
|
+
static build(opts?: {
|
|
14
|
+
severity?: TRuleSeverity;
|
|
15
|
+
}): TRuleSeverity;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=effect-cleanup-consistency.rule.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"effect-cleanup-consistency.rule.d.ts","sourceRoot":"","sources":["../../../src/linters/house/effect-cleanup-consistency.rule.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AACnC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAarD;;;;;;GAMG;AACH,qBAAa,4BAA4B;IACvC,MAAM,CAAC,QAAQ,CAAC,IAAI,wCAA0D;IAE9E,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,UAAU,CA2EnC;IAEF,MAAM,CAAC,KAAK,CAAC,IAAI,GAAE;QAAE,QAAQ,CAAC,EAAE,aAAa,CAAA;KAAO,GAAG,aAAa;CAGrE"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.EffectCleanupConsistencyRule = void 0;
|
|
4
|
+
const common_1 = require("./common");
|
|
5
|
+
const hook_support_1 = require("./hook-support");
|
|
6
|
+
/**
|
|
7
|
+
* `venizia/effect-cleanup-consistency`. The callback of `useEffect`, `useLayoutEffect` and `useInsertionEffect`
|
|
8
|
+
* returns a cleanup on every path or on none. An early `return;` beside a later `return () => {}` leaves React
|
|
9
|
+
* with a cleanup on some runs only; the early exit returns a no-op instead. A bare `return;` and falling off the
|
|
10
|
+
* end both mean "no value". It uses ESLint's code path analysis the way `consistent-return` does, so an
|
|
11
|
+
* unreachable end of the function is not a path. A nested function's own `return` is not counted.
|
|
12
|
+
*/
|
|
13
|
+
class EffectCleanupConsistencyRule {
|
|
14
|
+
static { this.NAME = `${common_1.HOUSE_PLUGIN_NAMESPACE}/effect-cleanup-consistency`; }
|
|
15
|
+
static { this.RULE = {
|
|
16
|
+
meta: {
|
|
17
|
+
type: 'problem',
|
|
18
|
+
schema: [],
|
|
19
|
+
messages: {
|
|
20
|
+
inconsistent: 'The callback of `{{hook}}` returns a cleanup on some paths only; return one on every path (a no-op `() => {}` for an early exit) or on none.',
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
create: (context) => {
|
|
24
|
+
const targets = new Map();
|
|
25
|
+
let frame;
|
|
26
|
+
const checkExit = (node) => {
|
|
27
|
+
const current = frame;
|
|
28
|
+
if (!current?.hook ||
|
|
29
|
+
common_1.AstNode.getType({ node: common_1.AstNode.readField({ node, key: 'body' }) }) !== 'BlockStatement') {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const endIsReachable = [...current.segments].some((segment) => segment.reachable);
|
|
33
|
+
if (current.returnsValue && (current.returnsNothing || endIsReachable)) {
|
|
34
|
+
context.report({ node, messageId: 'inconsistent', data: { hook: current.hook } });
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
return {
|
|
38
|
+
[common_1.AstNodeTypes.CALL_EXPRESSION]: (node) => {
|
|
39
|
+
const hook = hook_support_1.HookSupport.calleeName({ call: node });
|
|
40
|
+
const args = common_1.AstNode.readField({ node, key: 'arguments' });
|
|
41
|
+
if (!hook_support_1.HookSupport.isEffectHook({ name: hook }) ||
|
|
42
|
+
hook === undefined ||
|
|
43
|
+
!Array.isArray(args)) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
if (hook_support_1.HookSupport.isCallback({ node: args[0] })) {
|
|
47
|
+
targets.set(args[0], hook);
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
onCodePathStart: (_codePath, node) => {
|
|
51
|
+
frame = {
|
|
52
|
+
upper: frame,
|
|
53
|
+
hook: targets.get(node),
|
|
54
|
+
returnsValue: false,
|
|
55
|
+
returnsNothing: false,
|
|
56
|
+
segments: new Set(),
|
|
57
|
+
};
|
|
58
|
+
},
|
|
59
|
+
onCodePathEnd: () => {
|
|
60
|
+
frame = frame?.upper;
|
|
61
|
+
},
|
|
62
|
+
onCodePathSegmentStart: (segment) => frame?.segments.add(segment),
|
|
63
|
+
onCodePathSegmentEnd: (segment) => frame?.segments.delete(segment),
|
|
64
|
+
onUnreachableCodePathSegmentStart: (segment) => frame?.segments.add(segment),
|
|
65
|
+
onUnreachableCodePathSegmentEnd: (segment) => frame?.segments.delete(segment),
|
|
66
|
+
[common_1.AstNodeTypes.RETURN_STATEMENT]: (node) => {
|
|
67
|
+
if (!frame) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
if (common_1.AstNode.readField({ node, key: 'argument' })) {
|
|
71
|
+
frame.returnsValue = true;
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
frame.returnsNothing = true;
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
'FunctionExpression:exit': checkExit,
|
|
78
|
+
'ArrowFunctionExpression:exit': checkExit,
|
|
79
|
+
};
|
|
80
|
+
},
|
|
81
|
+
}; }
|
|
82
|
+
static build(opts = {}) {
|
|
83
|
+
return opts.severity ?? 'error';
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
exports.EffectCleanupConsistencyRule = EffectCleanupConsistencyRule;
|
|
87
|
+
//# sourceMappingURL=effect-cleanup-consistency.rule.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"effect-cleanup-consistency.rule.js","sourceRoot":"","sources":["../../../src/linters/house/effect-cleanup-consistency.rule.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Rule } from 'eslint';\nimport type { TRuleSeverity } from '../rules/common';\nimport { AstNode, AstNodeTypes, HOUSE_PLUGIN_NAMESPACE } from './common';\nimport { HookSupport } from './hook-support';\n\n/** What the rule knows about the function whose code path is open; one per function, so a nested function is its own. */\ninterface IFunctionFrame {\n upper: IFunctionFrame | undefined;\n hook: string | undefined;\n returnsValue: boolean;\n returnsNothing: boolean;\n segments: Set<{ reachable: boolean }>;\n}\n\n/**\n * `venizia/effect-cleanup-consistency`. The callback of `useEffect`, `useLayoutEffect` and `useInsertionEffect`\n * returns a cleanup on every path or on none. An early `return;` beside a later `return () => {}` leaves React\n * with a cleanup on some runs only; the early exit returns a no-op instead. A bare `return;` and falling off the\n * end both mean \"no value\". It uses ESLint's code path analysis the way `consistent-return` does, so an\n * unreachable end of the function is not a path. A nested function's own `return` is not counted.\n */\nexport class EffectCleanupConsistencyRule {\n static readonly NAME = `${HOUSE_PLUGIN_NAMESPACE}/effect-cleanup-consistency`;\n\n static readonly RULE: Rule.RuleModule = {\n meta: {\n type: 'problem',\n schema: [],\n messages: {\n inconsistent:\n 'The callback of `{{hook}}` returns a cleanup on some paths only; return one on every path (a no-op `() => {}` for an early exit) or on none.',\n },\n },\n create: (context) => {\n const targets = new Map<unknown, string>();\n let frame: IFunctionFrame | undefined;\n\n const checkExit = (node: Rule.Node) => {\n const current = frame;\n if (\n !current?.hook ||\n AstNode.getType({ node: AstNode.readField({ node, key: 'body' }) }) !== 'BlockStatement'\n ) {\n return;\n }\n\n const endIsReachable = [...current.segments].some((segment) => segment.reachable);\n if (current.returnsValue && (current.returnsNothing || endIsReachable)) {\n context.report({ node, messageId: 'inconsistent', data: { hook: current.hook } });\n }\n };\n\n return {\n [AstNodeTypes.CALL_EXPRESSION]: (node: Rule.Node) => {\n const hook = HookSupport.calleeName({ call: node });\n const args = AstNode.readField({ node, key: 'arguments' });\n if (\n !HookSupport.isEffectHook({ name: hook }) ||\n hook === undefined ||\n !Array.isArray(args)\n ) {\n return;\n }\n\n if (HookSupport.isCallback({ node: args[0] })) {\n targets.set(args[0], hook);\n }\n },\n onCodePathStart: (_codePath, node) => {\n frame = {\n upper: frame,\n hook: targets.get(node),\n returnsValue: false,\n returnsNothing: false,\n segments: new Set(),\n };\n },\n onCodePathEnd: () => {\n frame = frame?.upper;\n },\n onCodePathSegmentStart: (segment) => frame?.segments.add(segment),\n onCodePathSegmentEnd: (segment) => frame?.segments.delete(segment),\n onUnreachableCodePathSegmentStart: (segment) => frame?.segments.add(segment),\n onUnreachableCodePathSegmentEnd: (segment) => frame?.segments.delete(segment),\n [AstNodeTypes.RETURN_STATEMENT]: (node: Rule.Node) => {\n if (!frame) {\n return;\n }\n\n if (AstNode.readField({ node, key: 'argument' })) {\n frame.returnsValue = true;\n } else {\n frame.returnsNothing = true;\n }\n },\n 'FunctionExpression:exit': checkExit,\n 'ArrowFunctionExpression:exit': checkExit,\n };\n },\n };\n\n static build(opts: { severity?: TRuleSeverity } = {}): TRuleSeverity {\n return opts.severity ?? 'error';\n }\n}\n"]}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/** The shared parts of the two hook rules: which call is a hook, and which argument is a function. */
|
|
2
|
+
export declare class HookSupport {
|
|
3
|
+
/** `useX(...)` and `React.useX(...)`: the name the call is made through, or `undefined` when it is not a plain name. */
|
|
4
|
+
static calleeName(opts: {
|
|
5
|
+
call: unknown;
|
|
6
|
+
}): string | undefined;
|
|
7
|
+
static isHook(opts: {
|
|
8
|
+
name: string | undefined;
|
|
9
|
+
}): boolean;
|
|
10
|
+
static isEffectHook(opts: {
|
|
11
|
+
name: string | undefined;
|
|
12
|
+
}): boolean;
|
|
13
|
+
/** An arrow or a function expression: the two forms a hook callback is written in. */
|
|
14
|
+
static isCallback(opts: {
|
|
15
|
+
node: unknown;
|
|
16
|
+
}): boolean;
|
|
17
|
+
static isAsync(opts: {
|
|
18
|
+
node: unknown;
|
|
19
|
+
}): boolean;
|
|
20
|
+
/**
|
|
21
|
+
* The async functions an argument hands over: the argument itself, a property value of an object literal
|
|
22
|
+
* (`useMutation({ mutationFn: async () => {} })`, an async method too) and an element of an array literal, at any
|
|
23
|
+
* depth of literals. It does not look inside a function: what a sync callback builds is not an argument.
|
|
24
|
+
*/
|
|
25
|
+
static asyncFunctionsIn(opts: {
|
|
26
|
+
node: unknown;
|
|
27
|
+
}): unknown[];
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=hook-support.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook-support.d.ts","sourceRoot":"","sources":["../../../src/linters/house/hook-support.ts"],"names":[],"mappings":"AAMA,sGAAsG;AACtG,qBAAa,WAAW;IACtB,wHAAwH;IACxH,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,OAAO,CAAA;KAAE,GAAG,MAAM,GAAG,SAAS;IAuB9D,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,GAAG,OAAO;IAI1D,MAAM,CAAC,YAAY,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,GAAG,OAAO;IAIhE,sFAAsF;IACtF,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO;IAInD,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO;IAMhD;;;;OAIG;IACH,MAAM,CAAC,gBAAgB,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,EAAE;CAgC5D"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HookSupport = void 0;
|
|
4
|
+
const common_1 = require("./common");
|
|
5
|
+
const HOOK_NAME = /^use[A-Z]/;
|
|
6
|
+
const EFFECT_HOOKS = new Set(['useEffect', 'useLayoutEffect', 'useInsertionEffect']);
|
|
7
|
+
const CALLBACK_TYPES = new Set(['ArrowFunctionExpression', 'FunctionExpression']);
|
|
8
|
+
/** The shared parts of the two hook rules: which call is a hook, and which argument is a function. */
|
|
9
|
+
class HookSupport {
|
|
10
|
+
/** `useX(...)` and `React.useX(...)`: the name the call is made through, or `undefined` when it is not a plain name. */
|
|
11
|
+
static calleeName(opts) {
|
|
12
|
+
const callee = common_1.AstNode.readField({ node: opts.call, key: 'callee' });
|
|
13
|
+
const type = common_1.AstNode.getType({ node: callee });
|
|
14
|
+
if (type === 'Identifier') {
|
|
15
|
+
const name = common_1.AstNode.readField({ node: callee, key: 'name' });
|
|
16
|
+
return typeof name === 'string' ? name : undefined;
|
|
17
|
+
}
|
|
18
|
+
if (type === 'MemberExpression' &&
|
|
19
|
+
common_1.AstNode.readField({ node: callee, key: 'computed' }) === false) {
|
|
20
|
+
const property = common_1.AstNode.readField({ node: callee, key: 'property' });
|
|
21
|
+
const name = common_1.AstNode.readField({ node: property, key: 'name' });
|
|
22
|
+
return common_1.AstNode.getType({ node: property }) === 'Identifier' && typeof name === 'string'
|
|
23
|
+
? name
|
|
24
|
+
: undefined;
|
|
25
|
+
}
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
static isHook(opts) {
|
|
29
|
+
return opts.name !== undefined && HOOK_NAME.test(opts.name);
|
|
30
|
+
}
|
|
31
|
+
static isEffectHook(opts) {
|
|
32
|
+
return opts.name !== undefined && EFFECT_HOOKS.has(opts.name);
|
|
33
|
+
}
|
|
34
|
+
/** An arrow or a function expression: the two forms a hook callback is written in. */
|
|
35
|
+
static isCallback(opts) {
|
|
36
|
+
return CALLBACK_TYPES.has(common_1.AstNode.getType({ node: opts.node }) ?? '');
|
|
37
|
+
}
|
|
38
|
+
static isAsync(opts) {
|
|
39
|
+
return (HookSupport.isCallback(opts) && common_1.AstNode.readField({ node: opts.node, key: 'async' }) === true);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* The async functions an argument hands over: the argument itself, a property value of an object literal
|
|
43
|
+
* (`useMutation({ mutationFn: async () => {} })`, an async method too) and an element of an array literal, at any
|
|
44
|
+
* depth of literals. It does not look inside a function: what a sync callback builds is not an argument.
|
|
45
|
+
*/
|
|
46
|
+
static asyncFunctionsIn(opts) {
|
|
47
|
+
const { node } = opts;
|
|
48
|
+
const type = common_1.AstNode.getType({ node });
|
|
49
|
+
if (HookSupport.isAsync({ node })) {
|
|
50
|
+
return [node];
|
|
51
|
+
}
|
|
52
|
+
if (type === 'ObjectExpression') {
|
|
53
|
+
const properties = common_1.AstNode.readField({ node, key: 'properties' });
|
|
54
|
+
return Array.isArray(properties)
|
|
55
|
+
? properties.flatMap((property) => common_1.AstNode.getType({ node: property }) === 'Property'
|
|
56
|
+
? HookSupport.asyncFunctionsIn({
|
|
57
|
+
node: common_1.AstNode.readField({ node: property, key: 'value' }),
|
|
58
|
+
})
|
|
59
|
+
: [])
|
|
60
|
+
: [];
|
|
61
|
+
}
|
|
62
|
+
if (type === 'ArrayExpression') {
|
|
63
|
+
const elements = common_1.AstNode.readField({ node, key: 'elements' });
|
|
64
|
+
return Array.isArray(elements)
|
|
65
|
+
? elements.flatMap((element) => HookSupport.asyncFunctionsIn({ node: element }))
|
|
66
|
+
: [];
|
|
67
|
+
}
|
|
68
|
+
return [];
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
exports.HookSupport = HookSupport;
|
|
72
|
+
//# sourceMappingURL=hook-support.js.map
|