Skip to content

Commit 2a71a4e

Browse files
authored
fix: fix plugins in resolvedConfig (#2213)
* fix: fix the plugins in resovledConfig * chore: fix tests + fix npm * chore: minor improvement * chore: minor improvement * chore: remove unused import
1 parent b097294 commit 2a71a4e

File tree

5 files changed

+99
-22
lines changed

5 files changed

+99
-22
lines changed

packages/core/src/config/__tests__/__snapshots__/config-resolvers.test.ts.snap

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,11 @@ exports[`resolveConfig > should resolve extends with local file config which con
534534
"overlay1Rules": {
535535
"info-contact": "off",
536536
},
537+
"plugins": [
538+
"api/plugin.js",
539+
"plugin.js",
540+
"api/plugin.js",
541+
],
537542
"preprocessors": {},
538543
"rules": {
539544
"boolean-parameter-prefixes": "error",

packages/core/src/config/__tests__/config-resolvers.test.ts

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,21 @@ import { resolveConfig } from '../config-resolvers.js';
55
import recommended from '../recommended.js';
66
import { fileURLToPath } from 'node:url';
77
import path from 'node:path';
8+
import { createRequire } from 'node:module';
89

910
import type { RawUniversalConfig, RawGovernanceConfig } from '../types.js';
1011
import { Source } from '../../resolve.js';
1112
import { Config } from '../config.js';
1213
import { SpecVersion } from '../../oas-types.js';
14+
import { after } from 'node:test';
15+
16+
vi.mock('node:module', () => ({
17+
default: {
18+
createRequire: () => ({
19+
resolve: (path: string) => `/mock/path/${path}`,
20+
}),
21+
},
22+
}));
1323

1424
const __dirname = path.dirname(fileURLToPath(import.meta.url));
1525

@@ -500,7 +510,9 @@ describe('resolveApis', () => {
500510
configPath
501511
),
502512
});
503-
const { resolvedConfig: mergedGovernancePresetResolved } = mergedGovernancePreset;
513+
const {
514+
resolvedConfig: { plugins, ...mergedGovernancePresetResolved },
515+
} = mergedGovernancePreset;
504516
const rawConfig: RawUniversalConfig = {
505517
apis: {
506518
petstore: {
@@ -597,4 +609,29 @@ describe('resolveApis', () => {
597609
expect(plugins?.length).toEqual(2);
598610
expect(rules?.['operation-2xx-response']).toEqual('warn');
599611
});
612+
613+
it('should work with npm dependencies', async () => {
614+
after(() => {
615+
(globalThis as any).__webpack_require__ = undefined;
616+
(globalThis as any).__non_webpack_require__ = undefined;
617+
});
618+
619+
(globalThis as any).__webpack_require__ = () => {};
620+
(globalThis as any).__non_webpack_require__ = (p: string) =>
621+
p === '/mock/path/test-plugin'
622+
? {
623+
id: 'npm-test-plugin',
624+
}
625+
: {
626+
id: 'local-test-plugin',
627+
};
628+
629+
const { resolvedConfig } = await resolveConfig({
630+
rawConfigDocument: makeDocument(
631+
{ plugins: ['test-plugin', 'fixtures/plugin.cjs'] },
632+
configPath
633+
),
634+
});
635+
expect(resolvedConfig.plugins).toEqual(['test-plugin', 'fixtures/plugin.cjs']);
636+
});
600637
});

packages/core/src/config/config-resolvers.ts

Lines changed: 53 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@ const DEFAULT_PROJECT_PLUGIN_PATHS = ['@theme/plugin.js', '@theme/plugin.cjs', '
4343
// Cache instantiated plugins during a single execution
4444
const pluginsCache: Map<string, Plugin[]> = new Map();
4545

46+
export type PluginResolveInfo = {
47+
absolutePath: string;
48+
rawPath: string;
49+
isModule: boolean;
50+
};
51+
4652
export type ConfigOptions = {
4753
rawConfigDocument?: Document<RawUniversalConfig>;
4854
configPath?: string;
@@ -80,14 +86,19 @@ export async function resolveConfig({
8086
externalRefResolver: externalRefResolver ?? new BaseResolver(getResolveConfig(config?.resolve)),
8187
});
8288

89+
let pluginsOrPaths: (Plugin | PluginResolveInfo)[] = [];
8390
let resolvedPlugins: Plugin[];
91+
let rootConfigDir: string = '';
8492
if (isBrowser) {
8593
// In browser, we don't support plugins from config file yet
8694
resolvedPlugins = [defaultPlugin];
8795
} else {
88-
const rootConfigDir = path.dirname(configPath ?? '');
89-
const pluginsOrPaths = collectConfigPlugins(rootDocument, resolvedRefMap, rootConfigDir);
90-
const plugins = await resolvePlugins(pluginsOrPaths, rootConfigDir);
96+
rootConfigDir = path.dirname(configPath ?? '');
97+
pluginsOrPaths = collectConfigPlugins(rootDocument, resolvedRefMap, rootConfigDir);
98+
const plugins = await resolvePlugins(
99+
pluginsOrPaths.map((p) => (isPluginResolveInfo(p) ? p.absolutePath : p)),
100+
rootConfigDir
101+
);
91102
resolvedPlugins = [...plugins, defaultPlugin];
92103
}
93104

@@ -106,8 +117,21 @@ export async function resolveConfig({
106117
);
107118
}
108119

120+
const pluginPaths = pluginsOrPaths.length
121+
? pluginsOrPaths
122+
.map((p) =>
123+
isPluginResolveInfo(p) && p.isModule
124+
? p.rawPath
125+
: p.absolutePath && path.relative(rootConfigDir, p.absolutePath)
126+
)
127+
.filter(isDefined)
128+
: undefined;
129+
109130
return {
110-
resolvedConfig: bundledConfig,
131+
resolvedConfig: {
132+
...bundledConfig,
133+
plugins: pluginPaths,
134+
},
111135
resolvedRefMap,
112136
plugins: resolvedPlugins,
113137
};
@@ -123,28 +147,35 @@ function getDefaultPluginPath(configDir: string): string | undefined {
123147
return;
124148
}
125149

150+
function isPluginResolveInfo(plugin: Plugin | PluginResolveInfo): plugin is PluginResolveInfo {
151+
return 'isModule' in plugin;
152+
}
153+
126154
export const preResolvePluginPath = (
127155
plugin: string | Plugin,
128156
base: string,
129157
rootConfigDir: string
130-
) => {
158+
): Plugin | PluginResolveInfo => {
131159
if (!isString(plugin)) {
132160
return plugin;
133161
}
134162

135163
const maybeAbsolutePluginPath = path.resolve(path.dirname(base), plugin);
136164

137165
return fs.existsSync(maybeAbsolutePluginPath)
138-
? maybeAbsolutePluginPath
139-
: // For plugins imported from packages specifically
140-
module.createRequire(import.meta.url ?? __dirname).resolve(plugin, {
141-
paths: [
142-
// Plugins imported from the node_modules in the project directory
143-
rootConfigDir,
144-
// Plugins imported from the node_modules in the package install directory (for example, npx cache directory)
145-
import.meta.url ? path.dirname(url.fileURLToPath(import.meta.url)) : __dirname,
146-
],
147-
});
166+
? { absolutePath: maybeAbsolutePluginPath, rawPath: plugin, isModule: false }
167+
: {
168+
absolutePath: module.createRequire(import.meta.url ?? __dirname).resolve(plugin, {
169+
paths: [
170+
// Plugins imported from the node_modules in the project directory
171+
rootConfigDir,
172+
// Plugins imported from the node_modules in the package install directory (for example, npx cache directory)
173+
import.meta.url ? path.dirname(url.fileURLToPath(import.meta.url)) : __dirname,
174+
],
175+
}),
176+
isModule: true,
177+
rawPath: plugin,
178+
};
148179
};
149180

150181
export async function resolvePlugins(
@@ -162,11 +193,13 @@ export async function resolvePlugins(
162193
try {
163194
const absolutePluginPath = path.isAbsolute(plugin)
164195
? plugin
165-
: (preResolvePluginPath(
166-
plugin,
167-
path.join(configDir, CONFIG_FILE_NAME),
168-
configDir
169-
) as string);
196+
: (
197+
preResolvePluginPath(
198+
plugin,
199+
path.join(configDir, CONFIG_FILE_NAME),
200+
configDir
201+
) as PluginResolveInfo
202+
).absolutePath;
170203

171204
if (!pluginsCache.has(absolutePluginPath)) {
172205
let requiredPlugin: ImportedPlugin | undefined;

packages/core/src/config/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@ export type RawUniversalConfig = Omit<Partial<RedoclyConfig>, 'apis' | 'plugins'
225225
export type ResolvedConfig = Omit<RawUniversalConfig, 'apis' | 'plugins'> &
226226
ResolvedGovernanceConfig & {
227227
apis?: Record<string, ResolvedApiConfig>;
228+
plugins?: string[];
228229
};
229230

230231
export type ThemeConfig = {

packages/core/src/config/visitors.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,13 @@ import { replaceRef } from '../ref-utils.js';
44
import { bundleExtends } from './bundle-extends.js';
55
import { preResolvePluginPath } from './config-resolvers.js';
66

7+
import type { PluginResolveInfo } from './config-resolvers.js';
78
import type { OasRef } from '../typings/openapi.js';
89
import type { Plugin } from './types.js';
910
import type { ResolveResult, UserContext } from '../walk.js';
1011

1112
export type PluginsCollectorVisitorData = {
12-
plugins: (string | Plugin)[];
13+
plugins: (PluginResolveInfo | Plugin)[];
1314
rootConfigDir: string;
1415
};
1516

0 commit comments

Comments
 (0)