Skip to content

Commit ec4a0ee

Browse files
committed
refactor(search): centralize pf search, get resources
* options.defaults, refactor for initial pf versions * pf.getResources, api prep, centralize all pf related data * pf.helpers, pf versions from options, disable findClosestPFVersion * pf.search, refactor, centralize pf search
1 parent 1df4434 commit ec4a0ee

11 files changed

Lines changed: 857 additions & 30 deletions

jest.config.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,10 @@ export default {
3232
{
3333
...tsConfig,
3434
diagnostics: {
35-
ignoreCodes: [1343]
35+
// See codes https://github.com/Microsoft/TypeScript/blob/main/src/compiler/diagnosticMessages.json
36+
// 1324 - Dynamic imports only support a second argument when the '--module' option is...
37+
// 1343 - The 'import.meta' meta-property is only allowed when the '--module' option is...
38+
ignoreCodes: [1324, 1343]
3639
},
3740
astTransformers: {
3841
before: [

src/__tests__/__snapshots__/options.defaults.test.ts.snap

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,18 @@ exports[`options defaults should return specific properties: defaults 1`] = `
3434
"availableResourceVersions": [
3535
"6.0.0",
3636
],
37+
"availableSchemasVersions": [
38+
"v6",
39+
],
40+
"availableSearchVersions": [
41+
"current",
42+
"latest",
43+
"v6",
44+
],
3745
"default": {
38-
"defaultVersion": "6.0.0",
46+
"latestSchemasVersion": "v6",
47+
"latestSemVer": "6.0.0",
48+
"latestVersion": "v6",
3949
"versionStrategy": "highest",
4050
"versionWhitelist": [
4151
"@patternfly/react-core",
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
2+
3+
exports[`getPatternFlyMcpResources should return multiple organized facets: properties 1`] = `
4+
[
5+
"availableVersions",
6+
"availableSchemasVersions",
7+
"enumeratedVersions",
8+
"envSemVer",
9+
"envVersion",
10+
"latestVersion",
11+
"latestSchemasVersion",
12+
"isEnvTheLatestVersion",
13+
"isEnvTheLatestSchemasVersion",
14+
"resources",
15+
"docsIndex",
16+
"componentsIndex",
17+
"keywordsIndex",
18+
"isFallbackDocumentation",
19+
"pathIndex",
20+
"byPath",
21+
"byUri",
22+
"byVersion",
23+
"byVersionComponentNames",
24+
]
25+
`;
26+
27+
exports[`getPatternFlyReactComponentNames should return multiple organized facets: properties 1`] = `
28+
[
29+
"byVersion",
30+
"componentNamesIndex",
31+
"componentNamesWithSchemasIndex",
32+
"componentNamesWithSchemasMap",
33+
]
34+
`;
35+
36+
exports[`setCategoryDisplayLabel should normalize categories and apply linking markdown, accessibility 1`] = `"Accessibility"`;
37+
38+
exports[`setCategoryDisplayLabel should normalize categories and apply linking markdown, design 1`] = `"Design Guidelines"`;
39+
40+
exports[`setCategoryDisplayLabel should normalize categories and apply linking markdown, empty string 1`] = `"Documentation"`;
41+
42+
exports[`setCategoryDisplayLabel should normalize categories and apply linking markdown, example 1`] = `"Examples"`;
43+
44+
exports[`setCategoryDisplayLabel should normalize categories and apply linking markdown, guidelines 1`] = `"AI Guidance"`;
45+
46+
exports[`setCategoryDisplayLabel should normalize categories and apply linking markdown, null 1`] = `"Documentation"`;
47+
48+
exports[`setCategoryDisplayLabel should normalize categories and apply linking markdown, undefined 1`] = `"Documentation"`;
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
2+
3+
exports[`searchPatternFly should return an array of search results: keys 1`] = `
4+
[
5+
"isSearchWildCardAll",
6+
"firstExactMatch",
7+
"exactMatches",
8+
]
9+
`;
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
import {
2+
setCategoryDisplayLabel,
3+
getPatternFlyComponentSchema,
4+
getPatternFlyReactComponentNames,
5+
getPatternFlyMcpResources
6+
} from '../patternFly.getResources';
7+
8+
describe('setCategoryDisplayLabel', () => {
9+
it.each([
10+
{
11+
description: 'empty string',
12+
entry: ''
13+
},
14+
{
15+
description: 'undefined',
16+
entry: undefined
17+
},
18+
{
19+
description: 'null',
20+
entry: null
21+
},
22+
{
23+
description: 'design',
24+
entry: {
25+
displayName: 'Lorem Ipsum',
26+
section: 'components',
27+
category: 'design-guidelines',
28+
path: 'https://www.patternfly.org/v6/components/lorem-ipsum/design-guidelines'
29+
}
30+
},
31+
{
32+
description: 'accessibility',
33+
entry: {
34+
displayName: 'Dolor Sit',
35+
section: 'components',
36+
category: 'accessibility',
37+
path: 'https://www.patternfly.org/v6/components/dolor-sit/accessibility'
38+
}
39+
},
40+
{
41+
description: 'example',
42+
entry: {
43+
displayName: 'Lorem Sit',
44+
section: 'components',
45+
category: 'react',
46+
path: 'https://www.patternfly.org/v6/components/lorem-sit/components'
47+
}
48+
},
49+
{
50+
description: 'guidelines',
51+
entry:
52+
{
53+
displayName: 'Sit Sit',
54+
section: 'guidelines',
55+
category: 'react',
56+
path: 'documentation:components/sit-sit/guidelines.md'
57+
}
58+
}
59+
])('should normalize categories and apply linking markdown, $description', ({ entry }) => {
60+
expect(setCategoryDisplayLabel(entry as any)).toMatchSnapshot();
61+
});
62+
});
63+
64+
describe('getPatternFlyComponentSchema', () => {
65+
it.each([
66+
{
67+
description: 'default',
68+
componentName: 'Button',
69+
expected: true
70+
},
71+
{
72+
description: 'unknown component',
73+
componentName: 'Lorem',
74+
expected: false
75+
}
76+
])('should attempt to return a schema', async ({ componentName, expected }) => {
77+
const output = await getPatternFlyComponentSchema(componentName);
78+
79+
expect(Boolean(output)).toBe(expected);
80+
});
81+
82+
it('should have a memoized property', () => {
83+
expect(getPatternFlyComponentSchema).toHaveProperty('memo');
84+
});
85+
});
86+
87+
describe('getPatternFlyReactComponentNames', () => {
88+
it('should return multiple organized facets', async () => {
89+
const result = await getPatternFlyReactComponentNames();
90+
91+
expect(Object.keys(result)).toMatchSnapshot('properties');
92+
});
93+
94+
it('should have a memoized property', () => {
95+
expect(getPatternFlyReactComponentNames).toHaveProperty('memo');
96+
});
97+
});
98+
99+
describe('getPatternFlyMcpResources', () => {
100+
it('should return multiple organized facets', async () => {
101+
const result = await getPatternFlyMcpResources();
102+
103+
expect(Object.keys(result)).toMatchSnapshot('properties');
104+
});
105+
106+
it('should have a memoized property', async () => {
107+
expect(getPatternFlyMcpResources).toHaveProperty('memo');
108+
});
109+
});

src/__tests__/patternFly.helpers.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { findClosestPatternFlyVersion } from '../patternFly.helpers';
1+
import { disabled_findClosestPatternFlyVersion } from '../patternFly.helpers';
22
import { readLocalFileFunction } from '../server.getResources';
33
import { DEFAULT_OPTIONS } from '../options.defaults';
44

@@ -24,7 +24,7 @@ describe('findClosestPatternFlyVersion', () => {
2424
expected: '6.0.0'
2525
}
2626
])('should return default version if no package.json is found, $description', async ({ path, expected }) => {
27-
const version = await findClosestPatternFlyVersion(path as any);
27+
const version = await disabled_findClosestPatternFlyVersion(path as any);
2828

2929
expect(version).toBe(expected);
3030
});
@@ -143,11 +143,11 @@ describe('findClosestPatternFlyVersion', () => {
143143
}));
144144

145145
// Use the PF MCP package.json so we can override with "mockReadLocalFile". Override available resource versions.
146-
const version = await findClosestPatternFlyVersion(process.cwd(), {
146+
const version = await disabled_findClosestPatternFlyVersion(process.cwd(), {
147147
...DEFAULT_OPTIONS,
148148
patternflyOptions: {
149149
...DEFAULT_OPTIONS.patternflyOptions,
150-
availableResourceVersions: ['4.0.0', '5.0.0', '6.0.0']
150+
availableResourceVersions: ['4.0.0', '5.0.0', '6.0.0'] as any
151151
}
152152
});
153153

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { searchPatternFly } from '../patternFly.search';
2+
3+
describe('searchPatternFly', () => {
4+
it('should return an array of search results', async () => {
5+
const { searchResults, ...rest } = await searchPatternFly('*', { allowWildCardAll: true });
6+
7+
expect(searchResults.length).toBeGreaterThan(0);
8+
expect(Object.keys(rest)).toMatchSnapshot('keys');
9+
});
10+
11+
it('should find a suffix match', async () => {
12+
const { searchResults } = await searchPatternFly('utton');
13+
14+
expect(searchResults.filter(({ matchType }) => matchType === 'suffix')).toEqual([
15+
expect.objectContaining({
16+
item: expect.stringContaining('utton')
17+
})
18+
]);
19+
});
20+
});

src/options.defaults.ts

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ import { type ToolModule } from './server.toolsUser';
2020
* @property maxSearchLength - Maximum length for search strings.
2121
* @property recommendedMaxDocsToLoad - Recommended maximum number of docs to load.
2222
* @property {typeof MODE_LEVELS} mode - Specifies the mode of operation.
23+
* - `cli`: Command-line interface mode.
24+
* - `programmatic`: Programmatic interaction mode where the application is used as a library or API.
25+
* - `test`: Testing or debugging mode.
2326
* @property {ModeOptions} modeOptions - Mode-specific options.
2427
* @property name - Name of the package.
2528
* @property nodeVersion - Node.js major version.
@@ -159,18 +162,27 @@ interface ModeOptions {
159162
/**
160163
* PatternFly-specific options.
161164
*
162-
* @property availableResourceVersions List of intended available PatternFly resource versions to the MCP server.
165+
* @property availableResourceVersions List of available PatternFly resource versions to the MCP server.
166+
* @property availableSearchVersions List of available PatternFly search versions to the MCP server.
167+
* @property availableSchemasVersions List of available PatternFly schema versions to the MCP server.
163168
* @property default Default specific options.
164-
* @property default.defaultVersion Default PatternFly version.
169+
* @property default.latestSemVer Default PatternFly `SemVer` major version (e.g., '6.0.0').
170+
* @property default.latestVersion Default PatternFly `tag` major version, used for display and file paths (e.g., 'v6').
171+
* @property default.latestSchemasVersion Default PatternFly `tag` major version, used for schemas.
165172
* @property default.versionWhitelist List of mostly reliable dependencies to scan for when detecting the PatternFly version.
166173
* @property default.versionStrategy Strategy to use when multiple PatternFly versions are detected.
167174
* - 'highest': Use the highest major version found.
168175
* - 'lowest': Use the lowest major version found.
169176
*/
170177
interface PatternFlyOptions {
171-
availableResourceVersions: string[];
178+
availableResourceVersions: ('6.0.0')[];
179+
// availableSearchVersions: ('current' | 'detected' | 'latest' | 'v3' | 'v4' | 'v5' | 'v6')[];
180+
availableSearchVersions: ('current' | 'detected' | 'latest' | 'v6')[];
181+
availableSchemasVersions: ('v6')[];
172182
default: {
173-
defaultVersion: string;
183+
latestSemVer: '6.0.0';
184+
latestVersion: 'v6';
185+
latestSchemasVersion: 'v6';
174186
versionWhitelist: string[];
175187
versionStrategy: 'highest' | 'lowest';
176188
}
@@ -349,8 +361,12 @@ const LOG_BASENAME = 'pf-mcp:log';
349361
*/
350362
const PATTERNFLY_OPTIONS: PatternFlyOptions = {
351363
availableResourceVersions: ['6.0.0'],
364+
availableSearchVersions: ['current', 'latest', 'v6'],
365+
availableSchemasVersions: ['v6'],
352366
default: {
353-
defaultVersion: '6.0.0',
367+
latestSemVer: '6.0.0',
368+
latestVersion: 'v6',
369+
latestSchemasVersion: 'v6',
354370
versionWhitelist: [
355371
'@patternfly/react-core',
356372
'@patternfly/patternfly'
@@ -366,11 +382,6 @@ const URL_REGEX = /^(https?:)\/\//i;
366382

367383
/**
368384
* Available operational modes for the MCP server.
369-
*
370-
* Each mode represents an operational domain:
371-
* - `cli`: Command-line interface mode.
372-
* - `programmatic`: Programmatic interaction mode where the application is used as a library or API.
373-
* - `test`: Testing or debugging mode.
374385
*/
375386
const MODE_LEVELS: DefaultOptions['mode'][] = ['cli', 'programmatic', 'test'];
376387

0 commit comments

Comments
 (0)