@alint-js/plugin-js 0.7.2 → 0.7.3

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 CHANGED
@@ -9,6 +9,7 @@ The package default export is the plugin definition. Individual rule definitions
9
9
  The bundled `recommended` config enables these rules under the `js` plugin name:
10
10
 
11
11
  - `js/inline-miniature-normalizer` reports clusters of local helpers that form a private reader or narrowing toolkit.
12
+ - `js/no-config-file-tests` reports standalone tests that restate repository configuration instead of verifying behavior. It skips non-test files before calling the model, but the `files:` glob must include tests and ignored files remain excluded.
12
13
  - `js/no-mixed-layers-without-abstraction` reports consuming features that own independently reusable external-integration responsibilities without a stable interface.
13
14
  - `js/no-private-schema-toolkit` reports clusters of local helpers that form an ad hoc schema or payload-normalization toolkit.
14
15
  - `js/no-redundant-binding` reports local bindings that only rename an unchanged value or reference without adding a useful boundary.
@@ -30,6 +31,8 @@ Five repository-aware rules are registered but intentionally not enabled by `rec
30
31
 
31
32
  The five opt-in rules require both a configured model and an agent adapter capable of tool calls. They reuse the standard `@alint-js/tools-fs` list, search, and read tools, and ask the agent to include repository evidence with each finding.
32
33
 
34
+ `js/no-config-file-tests` is not repository-aware and needs no agent adapter: it judges the test file it is handed, so a configured model is enough.
35
+
33
36
  ## How to use
34
37
 
35
38
  Use the default export with the `js` plugin name because the bundled preset refers to `js/*` rule IDs.
@@ -88,6 +91,7 @@ export default defineConfig([
88
91
 
89
92
  - Do not use model-backed rules as a deterministic replacement for syntax-aware lint.
90
93
  - Do not enable repository-aware rules with a generation-only model or without an agent adapter.
94
+ - Do not use `js/no-config-file-tests` when the configuration module owns logic the repository must verify, such as a custom lint rule, a custom bundler plugin, or a merge or normalization helper. Move that logic into its own module and test the module instead.
91
95
  - Do not use `js/no-duplicated-knowledge` for coincidental literals or clones that do not encode one shared decision.
92
96
  - Do not use `js/no-overlapping-entrypoints` for documented compatibility aliases or conditional/type-only exports.
93
97
  - Do not use `js/no-redundant-catch` when the outer catch changes cleanup, observability, error metadata, cause, identity, or cancellation behavior.
package/dist/index.d.mts CHANGED
@@ -2605,6 +2605,9 @@ declare function createReportFindingsToolParameters(): JsonSchema;
2605
2605
  //#region src/rules/inline-miniature-normalizer/rule.d.ts
2606
2606
  declare const inlineMiniatureNormalizerRule: RuleDefinition<[]>;
2607
2607
  //#endregion
2608
+ //#region src/rules/no-config-file-tests/rule.d.ts
2609
+ declare const configFileTestsRule: RuleDefinition<[]>;
2610
+ //#endregion
2608
2611
  //#region src/rules/no-duplicated-knowledge/rule.d.ts
2609
2612
  declare const duplicatedKnowledgeRule: RuleDefinition<[]>;
2610
2613
  //#endregion
@@ -2641,6 +2644,7 @@ declare const vacuousFunctionRule: RuleDefinition<[]>;
2641
2644
  //#region src/index.d.ts
2642
2645
  declare const _default: PluginDefinition<{
2643
2646
  readonly 'inline-miniature-normalizer': RuleDefinition<[]>;
2647
+ readonly 'no-config-file-tests': RuleDefinition<[]>;
2644
2648
  readonly 'no-duplicated-knowledge': RuleDefinition<[]>;
2645
2649
  readonly 'no-mixed-layers-without-abstraction': RuleDefinition<[]>;
2646
2650
  readonly 'no-overlapping-entrypoints': RuleDefinition<[]>;
@@ -2654,4 +2658,4 @@ declare const _default: PluginDefinition<{
2654
2658
  readonly 'no-vacuous-function': RuleDefinition<[]>;
2655
2659
  }>;
2656
2660
  //#endregion
2657
- export { createJudgeMessages, createReportFindingsToolParameters, _default as default, duplicatedKnowledgeRule, inlineMiniatureNormalizerRule, judgeFindingSchema, judgeResponseSchema, mixedLayersWithoutAbstractionRule, overlappingEntrypointsRule, privateSchemaToolkitRule, redundantBindingRule, redundantCatchRule, redundantJsdocRule, singleUseMaterializationRule, testOnlyProductionWrapperRule, trivialWrapperStackRule, vacuousFunctionRule };
2661
+ export { configFileTestsRule, createJudgeMessages, createReportFindingsToolParameters, _default as default, duplicatedKnowledgeRule, inlineMiniatureNormalizerRule, judgeFindingSchema, judgeResponseSchema, mixedLayersWithoutAbstractionRule, overlappingEntrypointsRule, privateSchemaToolkitRule, redundantBindingRule, redundantCatchRule, redundantJsdocRule, singleUseMaterializationRule, testOnlyProductionWrapperRule, trivialWrapperStackRule, vacuousFunctionRule };
package/dist/index.mjs CHANGED
@@ -2048,6 +2048,102 @@ async onTargetFile(target) {
2048
2048
  } })
2049
2049
  });
2050
2050
  //#endregion
2051
+ //#region src/rules/no-config-file-tests/prompt.ts
2052
+ const configFileTestsPrompt = `
2053
+ You are reviewing one JavaScript or TypeScript test file.
2054
+
2055
+ Task:
2056
+ Warn about a standalone test file whose subject is repository configuration rather than production behavior.
2057
+
2058
+ This is a warning-level design smell, not a correctness error.
2059
+
2060
+ The issue:
2061
+ Configuration is declarative, so a test that restates it keeps a second copy of values the configuration already states. Every intentional configuration change then fails the test without proving any behavior, and the same decision has to be updated in two places. A failing copy is also easy to misread: it looks like evidence that the configuration change is wrong.
2062
+
2063
+ Report test files whose subject is configuration, such as:
2064
+ - importing a configuration module like eslint.config.ts, vite.config.ts, vitest.config.ts, tsdown.config.ts, or alint.config.ts and asserting its exported object, arrays, globs, plugin lists, or rule severities
2065
+ - reading a configuration file as text or structured data, like tsconfig.json, package.json, or cspell.config.yaml, and asserting its keys, values, ordering, or a snapshot of it
2066
+ - asserting that a configuration entry contains an expected string, path, dependency, or file name, where the expectation is the configuration itself
2067
+
2068
+ Do not report:
2069
+ - tests for logic the repository owns: custom lint rule implementations, custom bundler or transformer plugins, configuration helper, merge, or normalization functions, schema validation, or environment-dependent branch selection
2070
+ - tests that run the configured tool over a fixture and assert the behavior or diagnostics it produces
2071
+ - tests that verify a generator produces configuration, when the generator is the unit under test
2072
+ - configuration that owns policy the repository must verify, such as permission or access lists, ignore lists that must stay in sync with another file, or a cross-file invariant the test proves
2073
+ - fixtures, snapshots, or helpers rather than tests that run
2074
+ - test files whose subject also includes production behavior
2075
+ - files that are not test files
2076
+
2077
+ Use an aggressive but fair standard:
2078
+ - if the assertions repeat values the configuration already declares, report it
2079
+ - if the test can only fail when a value it copied changes, report it
2080
+ - if deleting the test would lose no verified behavior, report it
2081
+ - if the subject is production code, or the configuration carries behavior that needs coverage, return no finding
2082
+
2083
+ Report the line that shows the configuration under test, usually the import of the configuration module or the assertion that restates it. Report each test file once, name the configuration under test or the values being restated, and keep the message short.
2084
+
2085
+ Suggest deleting the standalone test and covering the configuration through the behavior it produces. When the configuration carries logic that needs coverage, suggest moving that logic into its own module and testing the module instead.
2086
+
2087
+ Return warnings only.
2088
+ `.trim();
2089
+ //#endregion
2090
+ //#region src/rules/no-config-file-tests/rule.ts
2091
+ const TEST_FILE_SUFFIX = /\.(?:test|spec)\.[cm]?[jt]sx?$/;
2092
+ const TEST_DIRECTORY = /(?:^|\/)(?:__tests__|__test__)\//;
2093
+ const configFileTestsRule = defineRule({
2094
+ cacheKey: configFileTestsPrompt,
2095
+ create: (ctx) => ({
2096
+ /**
2097
+ * Reviews one test file target for a standalone test of configuration content.
2098
+ *
2099
+ * Triggering workflow:
2100
+ *
2101
+ * {@link defineRule}
2102
+ * -> `PlannedSourceTarget.kind === "file"`
2103
+ * -> `onTargetFile`
2104
+ * -> {@link judgeSource}
2105
+ *
2106
+ * Upstream:
2107
+ * - {@link defineRule}
2108
+ *
2109
+ * Downstream:
2110
+ * - {@link judgeSource}
2111
+ * - `ctx.report`
2112
+ */
2113
+ async onTargetFile(target) {
2114
+ if (!isTestFile(target.file.path)) return;
2115
+ const model = await ctx.model();
2116
+ const file = await ctx.src.readFile(target.file);
2117
+ const findings = await judgeSource({
2118
+ logger: ctx.logger,
2119
+ metering: ctx.metering,
2120
+ model,
2121
+ operation: "config-file-tests-judge",
2122
+ outputLanguage: ctx.outputLanguage,
2123
+ prompt: configFileTestsPrompt,
2124
+ signal: ctx.signal,
2125
+ source: file.text
2126
+ });
2127
+ for (const finding of findings) ctx.report({
2128
+ evidence: {
2129
+ confidence: finding.confidence,
2130
+ suggestion: finding.suggestion
2131
+ },
2132
+ filePath: target.file.path,
2133
+ loc: { start: {
2134
+ column: 0,
2135
+ line: finding.line
2136
+ } },
2137
+ message: finding.message
2138
+ });
2139
+ } }),
2140
+ languages: ["javascript", "typescript"]
2141
+ });
2142
+ function isTestFile(filePath) {
2143
+ const normalized = filePath.replace(/\\/g, "/");
2144
+ return TEST_FILE_SUFFIX.test(normalized) || TEST_DIRECTORY.test(normalized);
2145
+ }
2146
+ //#endregion
2051
2147
  //#region src/rules/no-duplicated-knowledge/prompt.ts
2052
2148
  const duplicatedKnowledgeInstructions = `
2053
2149
  Investigate whether the target independently maintains knowledge that the repository already owns elsewhere.
@@ -6232,6 +6328,7 @@ async onTargetFile(target) {
6232
6328
  var src_default = definePlugin({
6233
6329
  configs: { recommended: [{ rules: {
6234
6330
  "js/inline-miniature-normalizer": "warn",
6331
+ "js/no-config-file-tests": "warn",
6235
6332
  "js/no-mixed-layers-without-abstraction": "warn",
6236
6333
  "js/no-private-schema-toolkit": "warn",
6237
6334
  "js/no-redundant-binding": "warn",
@@ -6241,6 +6338,7 @@ var src_default = definePlugin({
6241
6338
  } }] },
6242
6339
  rules: {
6243
6340
  "inline-miniature-normalizer": inlineMiniatureNormalizerRule,
6341
+ "no-config-file-tests": configFileTestsRule,
6244
6342
  "no-duplicated-knowledge": duplicatedKnowledgeRule,
6245
6343
  "no-mixed-layers-without-abstraction": mixedLayersWithoutAbstractionRule,
6246
6344
  "no-overlapping-entrypoints": overlappingEntrypointsRule,
@@ -6255,4 +6353,4 @@ var src_default = definePlugin({
6255
6353
  }
6256
6354
  });
6257
6355
  //#endregion
6258
- export { createJudgeMessages, createReportFindingsToolParameters, src_default as default, duplicatedKnowledgeRule, inlineMiniatureNormalizerRule, judgeFindingSchema, judgeResponseSchema, mixedLayersWithoutAbstractionRule, overlappingEntrypointsRule, privateSchemaToolkitRule, redundantBindingRule, redundantCatchRule, redundantJsdocRule, singleUseMaterializationRule, dist_exports as t, testOnlyProductionWrapperRule, trivialWrapperStackRule, vacuousFunctionRule };
6356
+ export { configFileTestsRule, createJudgeMessages, createReportFindingsToolParameters, src_default as default, duplicatedKnowledgeRule, inlineMiniatureNormalizerRule, judgeFindingSchema, judgeResponseSchema, mixedLayersWithoutAbstractionRule, overlappingEntrypointsRule, privateSchemaToolkitRule, redundantBindingRule, redundantCatchRule, redundantJsdocRule, singleUseMaterializationRule, dist_exports as t, testOnlyProductionWrapperRule, trivialWrapperStackRule, vacuousFunctionRule };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@alint-js/plugin-js",
3
3
  "type": "module",
4
- "version": "0.7.2",
4
+ "version": "0.7.3",
5
5
  "description": "Model-backed JavaScript and TypeScript review rules for alint",
6
6
  "license": "MIT",
7
7
  "repository": {
@@ -32,9 +32,9 @@
32
32
  "@valibot/to-json-schema": "^1.7.1",
33
33
  "apeira": "^0.0.7",
34
34
  "valibot": "^1.4.2",
35
- "@alint-js/plugin": "0.7.2",
36
- "@alint-js/tools-fs": "0.7.2",
37
- "@alint-js/core": "0.7.2"
35
+ "@alint-js/core": "0.7.3",
36
+ "@alint-js/plugin": "0.7.3",
37
+ "@alint-js/tools-fs": "0.7.3"
38
38
  },
39
39
  "scripts": {
40
40
  "build": "tsdown",