Skip to content

Commit e87e496

Browse files
authored
Merge branch 'main' into chenjiahan/test-config-inheritance
2 parents 1c22392 + 2b8a15f commit e87e496

4 files changed

Lines changed: 38 additions & 9 deletions

File tree

‎AGENTS.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ pnpm --filter rstack test
3030

3131
## Testing
3232

33+
- Keep tests minimal and focused on observable behavior; avoid redundant coverage, implementation details, and unnecessary complexity.
3334
- Run `pnpm build` and `pnpm --filter rstack build:native` before `pnpm test`
3435

3536
## Native

‎packages/rstack/src/configLayers.ts‎

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ type ConfigArgs<K extends keyof Configs> = K extends 'app'
2828

2929
/**
3030
* Resolve one tool from ordered, normalized config layers. Lint factories are
31-
* already wrapped by define.lint; merging belongs to the tool adapters.
31+
* already wrapped by define.lint. This function does not merge the results.
3232
*/
3333
export const resolveConfigLayers = async <K extends keyof Configs>(
3434
layers: readonly Configs[],
@@ -56,3 +56,10 @@ export const resolveConfigLayers = async <K extends keyof Configs>(
5656

5757
return configs;
5858
};
59+
60+
export const resolveRslintConfig = async (
61+
layers: readonly Configs[],
62+
): Promise<RslintConfig | undefined> => {
63+
const configs = await resolveConfigLayers(layers, 'lint');
64+
return configs.length > 1 ? configs.flat() : configs[0];
65+
};

‎packages/rstack/src/rslintConfig.ts‎

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,19 @@ import { join } from 'node:path';
33
import { loadRstackConfig, type LoadedRstackConfig } from './config.ts';
44
import type { RslintConfig } from '@rslint/core';
55
import { color, logger } from 'rslog';
6+
import { resolveRslintConfig } from './configLayers.ts';
67

78
// Expose the loaded config so `rs check` can pass it to fmt instead of loading
89
// and executing the Rstack config a second time.
910
export const loadedConfig: LoadedRstackConfig = await loadRstackConfig();
1011
const { configs } = loadedConfig;
11-
const lintDefinition = configs.lint;
12+
const lintConfig = await resolveRslintConfig([configs]);
1213

13-
let lintConfig: RslintConfig;
14-
15-
if (lintDefinition === undefined) {
14+
if (lintConfig === undefined) {
1615
logger.error(
1716
`No lint configuration found. Add ${color.cyan('define.lint(...)')} to your Rstack config file.`,
1817
);
1918
process.exit(1);
20-
} else if (typeof lintDefinition === 'function') {
21-
lintConfig = await lintDefinition();
22-
} else {
23-
lintConfig = lintDefinition;
2419
}
2520

2621
const basePath = process.cwd();
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import type { RslintConfig } from '@rslint/core';
2+
import { expect, test } from 'rstack/test';
3+
import { normalizeRstackConfig } from '../../src/config.ts';
4+
import { resolveRslintConfig } from '../../src/configLayers.ts';
5+
6+
test('concatenates lint layers in order without merging entries', async () => {
7+
const shared: RslintConfig = [
8+
{ ignores: ['dist/**'] },
9+
[{ files: ['**/*.js'], rules: { 'no-debugger': 'error' } }],
10+
];
11+
const project: RslintConfig = [{ rules: { 'no-debugger': 'off' } }];
12+
13+
const config = await resolveRslintConfig([
14+
{ lint: shared },
15+
normalizeRstackConfig({ lint: () => Promise.resolve(project) }),
16+
]);
17+
18+
expect(config).toEqual([...shared, ...project]);
19+
});
20+
21+
test('preserves a single lint config and distinguishes missing from empty', async () => {
22+
const config: RslintConfig = [];
23+
24+
expect(await resolveRslintConfig([{}])).toBeUndefined();
25+
expect(await resolveRslintConfig([{}, { lint: config }])).toBe(config);
26+
});

0 commit comments

Comments
 (0)