Skip to content

Commit f8df903

Browse files
authored
refactor(config): move CLI path fallback to callers (#601)
1 parent 409e9a7 commit f8df903

15 files changed

Lines changed: 80 additions & 70 deletions

File tree

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { join, resolve } from 'node:path';
22
import { pathToFileURL } from 'node:url';
3-
import { CLI_CONFIG_PATH_ENV, getConfigState } from '../config.ts';
3+
import { CLI_CONFIG_PATH_ENV, getConfigState } from './config.ts';
44
import { insertConfigArg, parseArgs, parseCliArgs } from './args.ts';
55
import { hasHelpFlag, printCommandHelp } from './help.ts';
66

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

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import {
2+
loadRstackConfig,
3+
type LoadedRstackConfig,
4+
type LoadRstackConfigOptions,
5+
} from '../config.ts';
6+
7+
type ConfigState = {
8+
/**
9+
* Absolute config path from the global `--config` flag, resolved at parse
10+
* time so a later cwd (such as an LSP workspace root) cannot change it.
11+
*/
12+
configPath?: string;
13+
};
14+
15+
declare global {
16+
// rslint-disable-next-line no-var
17+
var __rstackCliState: ConfigState | undefined;
18+
}
19+
20+
export const getConfigState = (): ConfigState => {
21+
// The CLI and internal tool configs may be loaded as separate module instances.
22+
return (globalThis.__rstackCliState ??= {});
23+
};
24+
25+
/** Passes `--config` to Rslint's JS plugin workers, which run in a fresh realm. */
26+
export const CLI_CONFIG_PATH_ENV = 'RSTACK_CLI_CONFIG_PATH';
27+
28+
/** Loads a root tool config using the CLI path unless explicitly overridden. */
29+
export const loadCliRstackConfig = (
30+
options: LoadRstackConfigOptions = {},
31+
): Promise<LoadedRstackConfig> =>
32+
loadRstackConfig({
33+
...options,
34+
configFilePath: options.configFilePath ?? getConfigState().configPath,
35+
});

‎packages/rstack/src/config.ts‎

Lines changed: 4 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,9 @@ export type LoadRstackConfigOptions = {
8484
/**
8585
* The path to the Rstack config file, can be a relative or absolute path.
8686
* A relative path is resolved from `cwd`.
87-
* If `configFilePath` is omitted, the config path set by the CLI is used.
88-
* If neither path is provided, the function will search for the config file in `cwd`.
89-
* Pass `null` to search `cwd` and ignore the CLI config path.
87+
* If omitted, the function searches for the config file in `cwd`.
9088
*/
91-
configFilePath?: string | null;
89+
configFilePath?: string;
9290
/**
9391
* The directory the config file is searched in and relative config paths are resolved from.
9492
* Defaults to the current working directory.
@@ -102,21 +100,10 @@ type ConfigSession = {
102100
active: boolean;
103101
};
104102

105-
type ConfigState = {
106-
/**
107-
* Config file path from the global `--config` flag. Always absolute: the CLI
108-
* resolves it at parse time so it stays independent of later cwd choices
109-
* (`loadRstackConfig` may be called with an LSP workspace root as `cwd`).
110-
*/
111-
configPath?: string;
112-
};
113-
114103
declare global {
115104
// rslint-disable-next-line no-var
116105
var __rstackConfigSessionStorage:
117106
AsyncLocalStorage<ConfigSession> | undefined;
118-
// rslint-disable-next-line no-var
119-
var __rstackCliState: ConfigState | undefined;
120107
}
121108

122109
const getConfigSessionStorage = (): AsyncLocalStorage<ConfigSession> => {
@@ -131,23 +118,6 @@ const getConfigSessionStorage = (): AsyncLocalStorage<ConfigSession> => {
131118
return globalThis.__rstackConfigSessionStorage;
132119
};
133120

134-
export const getConfigState = (): ConfigState => {
135-
// The CLI and its internal tool config can also be loaded as separate module
136-
// instances. Keep only the CLI config path in its own global state.
137-
if (!globalThis.__rstackCliState) {
138-
globalThis.__rstackCliState = {};
139-
}
140-
141-
return globalThis.__rstackCliState;
142-
};
143-
144-
/**
145-
* Passes the `--config` path to Rslint's JS plugin workers, which import the
146-
* internal lint config in a fresh realm without the CLI state above. Only that
147-
* config reads it.
148-
*/
149-
export const CLI_CONFIG_PATH_ENV = 'RSTACK_CLI_CONFIG_PATH';
150-
151121
type Define = {
152122
/**
153123
* Inherits shared configs from left to right, followed by the project's own
@@ -269,9 +239,6 @@ export const loadRstackConfig = async ({
269239
configFilePath,
270240
cwd,
271241
}: LoadRstackConfigOptions = {}): Promise<LoadedRstackConfig> => {
272-
const state = getConfigState();
273-
const configPath =
274-
configFilePath === null ? undefined : (configFilePath ?? state.configPath);
275242
const session: ConfigSession = {
276243
configs: {},
277244
active: true,
@@ -284,8 +251,8 @@ export const loadRstackConfig = async ({
284251
exportName: false,
285252
fresh: true,
286253
cwd,
287-
...(configPath !== undefined
288-
? { path: configPath }
254+
...(configFilePath !== undefined
255+
? { path: configFilePath }
289256
: {
290257
configFileNames: [
291258
'rstack.config.ts',

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ import { performance } from 'node:perf_hooks';
33
import { color, logger } from 'rslog';
44
import { parseArgs } from '../cli/args.ts';
55
import { printCommandHelp } from '../cli/help.ts';
6-
import { loadRstackConfig, type LoadedRstackConfig } from '../config.ts';
6+
import type { LoadedRstackConfig } from '../config.ts';
7+
import { loadCliRstackConfig } from '../cli/config.ts';
78
import { ensureProjectCacheDir } from '../projectCache.ts';
89
import { fmtCacheFileName } from './cacheStore.ts';
910
import { resolveFmtConfig } from './config.ts';
@@ -250,7 +251,7 @@ const loadFmtConfig = async (
250251
loadedConfig?: LoadedRstackConfig,
251252
): Promise<ResolvedFmtConfig> => {
252253
const { configs, filePath } =
253-
loadedConfig ?? (await loadRstackConfig({ cwd }));
254+
loadedConfig ?? (await loadCliRstackConfig({ cwd }));
254255

255256
return resolveFmtConfig({
256257
layers: [configs],

‎packages/rstack/src/rsbuildConfig.ts‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ import {
55
mergeRsbuildConfig,
66
} from '@rsbuild/core';
77
import { withConfigMeta } from '@rstackjs/load-config';
8-
import { loadRstackConfig, type RstackConfigDefinitions } from './config.ts';
8+
import type { RstackConfigDefinitions } from './config.ts';
9+
import { loadCliRstackConfig } from './cli/config.ts';
910
import { resolveConfigLayers } from './configLayers.ts';
1011

1112
export const resolveRsbuildConfig = async (
@@ -19,7 +20,7 @@ export const resolveRsbuildConfig = async (
1920
};
2021

2122
const loadRsbuildConfig: RsbuildConfigDefinition = async (params) => {
22-
const { configs, filePath, dependencies } = await loadRstackConfig();
23+
const { configs, filePath, dependencies } = await loadCliRstackConfig();
2324
const config = await resolveRsbuildConfig([configs], params);
2425

2526
return withConfigMeta(config, { filePath, dependencies });

‎packages/rstack/src/rslibConfig.ts‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ import {
55
mergeRslibConfig,
66
} from '@rslib/core';
77
import { withConfigMeta } from '@rstackjs/load-config';
8-
import { loadRstackConfig, type RstackConfigDefinitions } from './config.ts';
8+
import type { RstackConfigDefinitions } from './config.ts';
9+
import { loadCliRstackConfig } from './cli/config.ts';
910
import { resolveConfigLayers } from './configLayers.ts';
1011

1112
export const resolveRslibConfig = async (
@@ -17,7 +18,7 @@ export const resolveRslibConfig = async (
1718
};
1819

1920
const loadRslibConfig = (async (params: ConfigParams) => {
20-
const { configs, filePath, dependencies } = await loadRstackConfig();
21+
const { configs, filePath, dependencies } = await loadCliRstackConfig();
2122
const config = await resolveRslibConfig([configs], params);
2223

2324
return withConfigMeta(config, { filePath, dependencies });

‎packages/rstack/src/rslintConfig.ts‎

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,15 @@
11
import { existsSync } from 'node:fs';
22
import { join } from 'node:path';
3-
import {
4-
CLI_CONFIG_PATH_ENV,
5-
loadRstackConfig,
6-
type LoadedRstackConfig,
7-
} from './config.ts';
3+
import { CLI_CONFIG_PATH_ENV, loadCliRstackConfig } from './cli/config.ts';
4+
import type { LoadedRstackConfig } from './config.ts';
85
import type { RslintConfig } from '@rslint/core';
96
import { color, logger } from 'rslog';
107
import { resolveRslintConfig } from './configLayers.ts';
118

129
// Expose the loaded config so `rs check` can pass it to fmt instead of loading
1310
// and executing the Rstack config a second time. Rslint also imports this
1411
// module in its JS plugin workers, which get `--config` from the environment.
15-
export const loadedConfig: LoadedRstackConfig = await loadRstackConfig({
12+
export const loadedConfig: LoadedRstackConfig = await loadCliRstackConfig({
1613
configFilePath: process.env[CLI_CONFIG_PATH_ENV],
1714
});
1815
const { configs } = loadedConfig;

‎packages/rstack/src/rspressConfig.ts‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { WatchFiles } from '@rsbuild/core';
22
import type { UserConfig } from '@rspress/core';
3-
import { loadRstackConfig, type RstackConfigDefinitions } from './config.ts';
3+
import type { RstackConfigDefinitions } from './config.ts';
4+
import { loadCliRstackConfig } from './cli/config.ts';
45
import { resolveConfigLayers } from './configLayers.ts';
56

67
export const resolveRspressConfig = async (
@@ -16,7 +17,7 @@ export const resolveRspressConfig = async (
1617
};
1718

1819
export default async (): Promise<UserConfig> => {
19-
const { configs, filePath, dependencies } = await loadRstackConfig();
20+
const { configs, filePath, dependencies } = await loadCliRstackConfig();
2021
const config = await resolveRspressConfig([configs]);
2122

2223
if (!filePath) {

‎packages/rstack/src/rstestConfig.ts‎

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
} from '@rstest/core';
88
import { type LoadProjectConfig, PROJECT_LOADER } from '@rstest/core/api';
99
import { loadRstackConfig, type RstackConfigDefinitions } from './config.ts';
10+
import { loadCliRstackConfig } from './cli/config.ts';
1011
import { resolveConfigLayers } from './configLayers.ts';
1112

1213
const resolveAutomaticExtends = async (
@@ -120,11 +121,9 @@ export const resolveRstestConfig = async (
120121
const createProjectLoader =
121122
(params: ConfigParams): LoadProjectConfig =>
122123
async ({ dirPath, filePath }) => {
123-
// `null` searches the project directory with the default config file names
124-
// instead of reusing the `rs --config` path that loads the root config.
125124
const loaded = await loadRstackConfig({
126125
cwd: dirPath,
127-
configFilePath: filePath ?? null,
126+
configFilePath: filePath,
128127
});
129128
if (loaded.filePath === null) {
130129
return null;
@@ -140,7 +139,7 @@ const createProjectLoader =
140139
};
141140

142141
const loadRstestConfig = (async (params: ConfigParams) => {
143-
const { configs } = await loadRstackConfig();
142+
const { configs } = await loadCliRstackConfig();
144143
const config = await resolveRstestConfig([configs], params);
145144
return {
146145
...config,

‎packages/rstack/src/staged.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import lintStaged from 'lint-staged';
22
import { parseArgs } from './cli/args.ts';
33
import { printCommandHelp } from './cli/help.ts';
4-
import { loadRstackConfig } from './config.ts';
4+
import { loadCliRstackConfig } from './cli/config.ts';
55
import { resolveStagedConfig } from './configLayers.ts';
66

77
export type StagedSyncTaskGenerator = (
@@ -51,7 +51,7 @@ export async function runStagedCLI(args: string[]): Promise<void> {
5151
return;
5252
}
5353

54-
const { configs } = await loadRstackConfig();
54+
const { configs } = await loadCliRstackConfig();
5555
const stagedConfig = await resolveStagedConfig([configs]);
5656
if (stagedConfig === undefined) {
5757
throw new Error(

0 commit comments

Comments
 (0)