Skip to content

Commit 5ceb4fc

Browse files
committed
refactor(config): shallowly merge format config layers
1 parent 5d6a10e commit 5ceb4fc

3 files changed

Lines changed: 55 additions & 6 deletions

File tree

‎packages/rstack/src/fmt/cli.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ const loadFmtConfig = async (
253253
loadedConfig ?? (await loadRstackConfig({ cwd }));
254254

255255
return resolveFmtConfig({
256-
definition: configs.fmt,
256+
layers: [configs],
257257
configFilePath: filePath,
258258
cwd,
259259
});

‎packages/rstack/src/fmt/config.ts‎

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
import { dirname } from 'node:path';
22
import micromatch from 'micromatch';
3+
import type { Configs } from '../config.ts';
4+
import { resolveConfigLayers } from '../configLayers.ts';
35
import { createRelativePathResolver } from './pathHelpers.ts';
46
import type {
57
FmtConfig,
6-
FmtConfigDefinition,
78
ResolvedFmtConfig,
89
ResolvedFmtOptions,
910
} from './types.ts';
1011

1112
type ResolveFmtConfigOptions = {
12-
definition: FmtConfigDefinition | undefined;
13+
layers: readonly Configs[];
1314
configFilePath: string | null;
1415
cwd: string;
1516
};
@@ -150,14 +151,17 @@ const createOptionsResolver = (
150151
};
151152
};
152153

153-
/** Resolves a formatter config definition and its project root. */
154+
/** Resolves formatter config layers and their project root. */
154155
const resolveFmtConfig = async ({
155-
definition,
156+
layers,
156157
configFilePath,
157158
cwd,
158159
}: ResolveFmtConfigOptions): Promise<ResolvedFmtConfig> => {
160+
const configs = await resolveConfigLayers(layers, 'fmt');
159161
const config =
160-
typeof definition === 'function' ? await definition() : definition;
162+
configs.length > 1
163+
? (Object.assign({}, ...configs) as FmtConfig)
164+
: configs[0];
161165
const rootPath = configFilePath ? dirname(configFilePath) : cwd;
162166

163167
return normalizeFmtConfig(config, rootPath);

‎packages/rstack/tests/fmt/config.test.ts‎

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,55 @@ import { expect, test } from 'rstack/test';
33
import {
44
createOptionsResolver,
55
normalizeFmtConfig,
6+
resolveFmtConfig,
67
} from '../../src/fmt/config.ts';
78

89
const rootPath = path.join(import.meta.dirname, 'project');
910

11+
test('shallowly merges fmt layers before normalizing options and overrides', async () => {
12+
const config = await resolveFmtConfig({
13+
layers: [
14+
{
15+
fmt: {
16+
singleQuote: true,
17+
semi: true,
18+
plugins: ['shared-plugin'],
19+
ignorePatterns: ['dist/**'],
20+
overrides: [{ files: '*.ts', options: { tabWidth: 8 } }],
21+
pluginOptions: { shared: true, project: false },
22+
},
23+
},
24+
{
25+
fmt: () =>
26+
Promise.resolve({
27+
semi: false,
28+
plugins: ['project-plugin'],
29+
ignorePatterns: ['generated/**'],
30+
overrides: [{ files: '*.ts', options: { semi: true } }],
31+
pluginOptions: { project: true },
32+
}),
33+
},
34+
],
35+
configFilePath: path.join(rootPath, 'rstack.config.ts'),
36+
cwd: path.dirname(rootPath),
37+
});
38+
39+
expect(config.rootPath).toBe(rootPath);
40+
expect(config.baseOptions).toEqual({
41+
singleQuote: true,
42+
semi: false,
43+
plugins: ['project-plugin'],
44+
pluginOptions: { project: true },
45+
});
46+
expect(config.ignorePatterns).toEqual(['generated/**']);
47+
expect(
48+
createOptionsResolver(config)(path.join(rootPath, 'index.ts')),
49+
).toEqual({
50+
...config.baseOptions,
51+
semi: true,
52+
});
53+
});
54+
1055
test('reuses base options when no override matches', () => {
1156
const config = normalizeFmtConfig(
1257
{

0 commit comments

Comments
 (0)