Skip to content

Commit 2d98249

Browse files
Merge pull request #1448 from opencomponents/custom-meta
add ability for custom meta query
2 parents 9a54a13 + 56d9f99 commit 2d98249

File tree

1 file changed

+88
-52
lines changed

1 file changed

+88
-52
lines changed

src/registry/routes/index.ts

Lines changed: 88 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,13 @@ const mapComponentDetails = (component: Component): ParsedComponent =>
2929
const isHtmlRequest = (headers: IncomingHttpHeaders) =>
3030
!!headers.accept && headers.accept.indexOf('text/html') >= 0;
3131

32+
const excludedMeta = ['dependencies', 'devDependencies'];
33+
3234
export default function (repository: Repository) {
3335
return async (req: Request, res: Response): Promise<void> => {
34-
let components: string[];
35-
36+
let componentNames: string[];
3637
try {
37-
components = await repository.getComponents();
38+
componentNames = await repository.getComponents();
3839
} catch {
3940
res.errorDetails = 'cdn not available';
4041
res.status(404).json({ error: res.errorDetails });
@@ -46,48 +47,49 @@ export default function (repository: Repository) {
4647
ocVersion: packageInfo.version,
4748
type: res.conf.local ? 'oc-registry-local' : 'oc-registry'
4849
};
49-
const componentResults = await Promise.all(
50-
components.map((component) =>
51-
repository.getComponent(component, undefined)
50+
51+
const componentDetails = await Promise.all(
52+
componentNames.map((componentName) =>
53+
repository.getComponent(componentName, undefined)
5254
)
5355
);
5456

5557
if (isHtmlRequest(req.headers) && !!res.conf.discovery.ui) {
56-
const componentsInfo: ParsedComponent[] = componentResults.map(
57-
(result) => {
58-
if (result.oc?.date) {
59-
result.oc.stringifiedDate = dateStringified(
60-
new Date(result.oc.date)
58+
const processedComponents: ParsedComponent[] = componentDetails.map(
59+
(component) => {
60+
if (component.oc?.date) {
61+
component.oc.stringifiedDate = dateStringified(
62+
new Date(component.oc.date)
6163
);
6264
}
63-
return mapComponentDetails(result);
65+
return mapComponentDetails(component);
6466
}
6567
);
6668

67-
const componentsReleases = componentResults.reduce(
68-
(sum, result) => sum + result.allVersions.length,
69+
const totalReleases = componentDetails.reduce(
70+
(sum, component) => sum + component.allVersions.length,
6971
0
7072
);
7173

7274
const stateCounts: { deprecated?: number; experimental?: number } = {};
73-
74-
const componentsList = componentsInfo.map((component) => {
75-
const state: 'deprecated' | 'experimental' | '' =
75+
const componentsList = processedComponents.map((component) => {
76+
const componentState: 'deprecated' | 'experimental' | '' =
7677
(component?.oc?.state as 'deprecated' | 'experimental' | '') || '';
77-
if (state) {
78-
stateCounts[state] = (stateCounts[state] || 0) + 1;
78+
79+
if (componentState) {
80+
stateCounts[componentState] = (stateCounts[componentState] || 0) + 1;
7981
}
82+
8083
return {
8184
name: component.name,
8285
author: component.author,
83-
state
86+
state: componentState
8487
};
8588
});
8689

87-
componentsInfo.sort((a, b) => a.name.localeCompare(b.name));
90+
processedComponents.sort((a, b) => a.name.localeCompare(b.name));
8891

89-
// Get theme from cookie or default to dark
90-
const theme = req.cookies?.['oc-theme'] || 'dark';
92+
const userTheme = req.cookies?.['oc-theme'] || 'dark';
9193

9294
res.send(
9395
indexView(
@@ -97,50 +99,84 @@ export default function (repository: Repository) {
9799
res.conf.dependencies
98100
),
99101
availablePlugins: res.conf.plugins,
100-
components: componentsInfo,
101-
componentsReleases,
102+
components: processedComponents,
103+
componentsReleases: totalReleases,
102104
componentsList,
103105
q: req.query['q'] || '',
104106
stateCounts,
105107
templates: repository.getTemplatesInfo(),
106108
title: 'OpenComponents Registry',
107-
theme
109+
theme: userTheme
108110
})
109111
)
110112
);
111113
} else {
112-
const state = req.query['state'] || '';
113-
const meta = req.query['meta'] === 'true' && res.conf.discovery.api;
114-
let list = componentResults;
114+
const requestedState = (req.query['state'] as string) || '';
115+
const includeMetadata =
116+
req.query['meta'] &&
117+
req.query['meta'] !== 'false' &&
118+
res.conf.discovery.api;
119+
120+
let filteredComponents = componentDetails;
121+
115122
if (!res.conf.discovery.experimental) {
116-
list = list.filter(
123+
filteredComponents = filteredComponents.filter(
117124
(component) => component.oc?.state !== 'experimental'
118125
);
119126
}
120-
if (state) {
121-
list = list.filter((component) => component.oc?.state === state);
127+
128+
if (requestedState) {
129+
filteredComponents = filteredComponents.filter(
130+
(component) => component.oc?.state === requestedState
131+
);
122132
}
123133

124-
res.status(200).json(
125-
Object.assign(baseResponse, {
126-
components: list.map((component) => {
127-
const href = urlBuilder.component(component.name, res.conf.baseUrl);
128-
129-
return meta
130-
? {
131-
href,
132-
name: component.name,
133-
version: component.version,
134-
author: component.author,
135-
description: component.description,
136-
state: component.oc.state,
137-
keywords: component.keywords || [],
138-
publishDate: new Date(component.oc.date).toISOString()
139-
}
140-
: href;
141-
})
142-
})
143-
);
134+
// Build component responses
135+
const componentResponses = filteredComponents.map((component) => {
136+
const componentUrl = urlBuilder.component(
137+
component.name,
138+
res.conf.baseUrl
139+
);
140+
141+
if (includeMetadata) {
142+
const metaQuery = req.query['meta'] as string;
143+
144+
// Return all metadata fields
145+
if (metaQuery === 'true') {
146+
return {
147+
href: componentUrl,
148+
name: component.name,
149+
version: component.version,
150+
author: component.author,
151+
description: component.description,
152+
state: component.oc.state,
153+
keywords: component.keywords || [],
154+
publishDate: new Date(component.oc.date).toISOString()
155+
};
156+
}
157+
158+
const requestedFields = metaQuery
159+
.split(',')
160+
.filter((field) => !excludedMeta.includes(field));
161+
const responseData = requestedFields.reduce(
162+
(acc, field) => {
163+
acc[field] = component[field as keyof Component];
164+
return acc;
165+
},
166+
{} as Record<string, any>
167+
);
168+
responseData['href'] = componentUrl;
169+
170+
return responseData;
171+
}
172+
173+
return componentUrl;
174+
});
175+
176+
res.status(200).json({
177+
...baseResponse,
178+
components: componentResponses
179+
});
144180
}
145181
};
146182
}

0 commit comments

Comments
 (0)