Skip to content

Commit

Permalink
Merge pull request #1363 from opencomponents/calculate-sizes
Browse files Browse the repository at this point in the history
calculate sizes on packaging and show in registry UI if available
  • Loading branch information
ricardo-devis-agullo committed Apr 7, 2024
2 parents 2cfbd07 + a75eba3 commit e812294
Show file tree
Hide file tree
Showing 10 changed files with 259 additions and 63 deletions.
38 changes: 37 additions & 1 deletion src/cli/domain/package-components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,38 @@ export interface PackageOptions {
production?: boolean;
}

interface Sizes {
client: number;
server?: number;
}

function checkSizes(folder: string) {
const jsFiles = fs.readdirSync(folder).filter(x => x.endsWith('.js'));

const sizes: Sizes = {
client: 0
};

for (const file of jsFiles) {
if (file === 'server.js') {
sizes.server = fs.statSync(path.join(folder, file)).size;
} else {
sizes.client += fs.statSync(path.join(folder, file)).size;
}
}

return sizes;
}

function addSizes(folder: string, component: Component, sizes: Sizes) {
component.oc.files.template.size = sizes.client;
if (sizes.server) {
component.oc.files.dataProvider.size = sizes.server;
}

fs.writeJsonSync(path.join(folder, 'package.json'), component, { spaces: 2 });
}

const packageComponents =
() =>
async (options: PackageOptions): Promise<Component> => {
Expand Down Expand Up @@ -55,7 +87,11 @@ const packageComponents =
componentPath
});
const compile = promisify(ocTemplate.compile);
return compile(compileOptions);
const component = await compile(compileOptions);

addSizes(publishPath, component, checkSizes(publishPath));

return component;
};

export default packageComponents;
3 changes: 2 additions & 1 deletion src/registry/domain/components-details.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ export default function componentsDetails(conf: Config, cdn: StorageAdapter) {
true
);
details.components[name][version] = {
publishDate: content.oc.date || 0
publishDate: content.oc.date || 0,
templateSize: content.oc.files.template.size
};
})
)
Expand Down
54 changes: 32 additions & 22 deletions src/registry/routes/component-info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import infoView from '../views/info';
import isUrlDiscoverable from './helpers/is-url-discoverable';
import * as urlBuilder from '../domain/url-builder';
import type { Repository } from '../domain/repository';
import { Component, Config } from '../../types';
import { Component, ComponentDetail, Config } from '../../types';
import { Request, Response } from 'express';

function getParams(component: Component) {
Expand Down Expand Up @@ -38,9 +38,10 @@ function componentInfo(
err: InfoError | string | null,
req: Request,
res: Response,
component: Component
component?: Component,
componentDetail?: ComponentDetail
): void {
if (err) {
if (!component || err) {
res.errorDetails = (err as any).registryError || err;
res.status(404).json(err);
return;
Expand All @@ -67,6 +68,7 @@ function componentInfo(
res.send(
infoView({
component,
componentDetail,
dependencies: Object.keys(component.dependencies || {}),
href,
parsedAuthor,
Expand All @@ -89,24 +91,32 @@ export default function componentInfoRoute(
conf: Config,
repository: Repository
) {
return function (req: Request, res: Response): void {
fromPromise(repository.getComponent)(
req.params['componentName'],
req.params['componentVersion'],
(registryError: any, component) => {
if (registryError && conf.fallbackRegistryUrl) {
return getComponentFallback.getComponentInfo(
conf,
req,
res,
registryError,
(fallbackError, fallbackComponent) =>
componentInfo(fallbackError, req, res, fallbackComponent)
);
}

componentInfo(registryError, req, res, component);
async function handler(req: Request, res: Response): Promise<void> {
try {
const history = await repository
.getComponentsDetails()
.catch(() => undefined);
const componentDetail = history?.components[req.params['componentName']];
const component = await repository.getComponent(
req.params['componentName'],
req.params['componentVersion']
);
componentInfo(null, req, res, component, componentDetail);
} catch (registryError) {
if (conf.fallbackRegistryUrl) {
return getComponentFallback.getComponentInfo(
conf,
req,
res,
registryError as any,
(fallbackError, fallbackComponent) =>
componentInfo(fallbackError, req, res, fallbackComponent)
);
}
);
};

componentInfo(registryError as any, req, res);
}
}

return handler;
}
4 changes: 4 additions & 0 deletions src/registry/routes/helpers/get-components-history.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ interface UnformmatedComponentHistory {
name: string;
version: string;
publishDate: number;
templateSize?: number;
}

interface ComponentHistory {
name: string;
version: string;
publishDate: string;
templateSize?: number;
}

export default function getComponentsHistory(
Expand All @@ -23,6 +25,7 @@ export default function getComponentsHistory(
result.push({
name,
publishDate: details.publishDate,
templateSize: details.templateSize,
version
});
}
Expand All @@ -33,6 +36,7 @@ export default function getComponentsHistory(
.map(x => ({
name: x.name,
version: x.version,
templateSize: x.templateSize,
publishDate: !x.publishDate
? 'Unknown'
: dateStringified(new Date(x.publishDate))
Expand Down
93 changes: 90 additions & 3 deletions src/registry/views/info.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component } from '../../types';
import { Component, ComponentDetail } from '../../types';

import getComponentAuthor from './partials/component-author';
import getComponentParameters from './partials/component-parameters';
Expand All @@ -12,13 +12,88 @@ import isTemplateLegacy from '../../utils/is-template-legacy';
interface Vm {
parsedAuthor: { name?: string; email?: string; url?: string };
component: Component;
componentDetail?: ComponentDetail;
dependencies: string[];
href: string;
sandBoxDefaultQs: string;
title: string;
repositoryUrl: string | null;
}

function statsJs(componentDetail: ComponentDetail) {
return `
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-date-fns/dist/chartjs-adapter-date-fns.bundle.min.js"></script>
<script>
(function () {
const componentDetail = ${JSON.stringify(componentDetail)};
const ctx = document.getElementById('stats');
const dataPoints = [];
const versionNumbers = Object.keys(componentDetail);
for (const versionNumber of versionNumbers) {
const versionData = componentDetail[versionNumber];
const date = new Date(versionData.publishDate);
const size = Math.round(versionData.templateSize / 1024);
// Add the data point to the array
dataPoints.push({ x: date, y: size, version: versionNumber });
}
const dataset = {
label: 'guest-stay-config',
data: dataPoints,
tension: 0.1,
borderWidth: 1
}
new Chart(ctx, {
type: 'line',
data: {
datasets: [dataset]
},
options: {
plugins: {
tooltip: {
callbacks: {
footer(items) {
const version = items[0].raw.version;
return 'Version: ' + version;
}
}
}
},
title: {
display: true,
text: "Package Sizes Over Time",
},
scales: {
x: {
type: "time",
time: {
unit: "day",
},
display: true,
title: {
display: true,
text: 'Date published'
}
},
y: {
display: true,
title: {
display: true,
text: 'Size in KB'
}
},
},
}
});
}());
</script>
`;
}

export default function info(vm: Vm): string {
const componentAuthor = getComponentAuthor(vm);
const componentParameters = getComponentParameters(vm);
Expand Down Expand Up @@ -49,10 +124,18 @@ export default function info(vm: Vm): string {
? 'legacy'
: compiler + '@' + component.oc.files.template.version
})`;
const statsAvailable =
!!vm.componentDetail && Object.keys(vm.componentDetail).length > 1;

const content = `<a class="back" href="${href}">&lt;&lt; All components</a>
<h2>${component.name} &nbsp;${componentVersions()}</h2>
<p class="w-100">${component.description} ${componentState()}</p>
${
statsAvailable
? `<h3>Stats</h3>
<canvas id="stats" width="400" height="200"></canvas>`
: ''
}
<h3>Component Info</h3>
${property('Repository', repositoryUrl || 'not available', !!repositoryUrl)}
${componentAuthor()}
Expand All @@ -61,6 +144,7 @@ export default function info(vm: Vm): string {
${property('Template', template)}
${showArray('Node.js dependencies', dependencies)}
${showArray('Plugin dependencies', component.oc.plugins)}
${component.oc.files.template.size ? property('Template size', `${Math.round(component.oc.files.template.size / 1024)} kb`) : ''}
${componentParameters()}
<h3>Code</h3>
<p>
Expand All @@ -81,9 +165,12 @@ export default function info(vm: Vm): string {
</h3>
<iframe class="preview" src="~preview/${sandBoxDefaultQs}"></iframe>`;

const scripts = `<script>var thisComponentHref="${href}${component.name}/";
const scripts = `
<script>var thisComponentHref="${href}${component.name}/";
${infoJS}
</script>`;
</script>
${statsAvailable ? statsJs(vm.componentDetail!) : ''}
`;

return layout({ content, scripts });
}
11 changes: 7 additions & 4 deletions src/registry/views/partials/components-history.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,20 @@ export default function componentsHistory(vm: VM): string {
const componentRow = ({
name,
publishDate,
version
version,
templateSize
}: {
name: string;
templateSize?: number;
publishDate: string;
version: string;
}) =>
`<a href="${name}/${version}/~info">
}) => {
return `<a href="${name}/${version}/~info">
<div class="componentRow row table">
<p class="release">${publishDate} - Published ${name}@${version}</p>
<p class="release">${publishDate} - Published ${name}@${version}${templateSize ? ` [${Math.round(templateSize / 1024)} kb]` : ''}</p>
</div>
</a>`;
};

const history = vm.componentsHistory || [];

Expand Down
24 changes: 18 additions & 6 deletions src/registry/views/partials/components-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,16 @@ import getSelectedCheckbox from './selected-checkbox';

export default function componentsList(vm: VM): string {
const isLocal = vm.type !== 'oc-registry';
const isRemote = !isLocal;
const sizeAvailable = vm.components.some(
component => component.oc.files.template.size
);
const selectedCheckbox = getSelectedCheckbox(vm);

const extraColumn = !isLocal
const remoteServerColumns = isRemote
? '<div class="date">Updated</div><div class="activity">Activity</div>'
: '';
const sizeColumn = sizeAvailable ? '<div>Size</div>' : '';

const componentRow = (component: ParsedComponent) => {
const componentState = component.oc.state
Expand All @@ -20,24 +25,30 @@ export default function componentsList(vm: VM): string {
component.oc.state === 'deprecated' ||
component.oc.state === 'experimental';

const extraColumn = !isLocal
const remoteServerColumns = isRemote
? `<div class="date">${
component.oc.stringifiedDate || ''
}</div><div class="activity">${component.allVersions.length}</div>`
: '';
const sizeColumn = sizeAvailable
? component.oc.files.template.size
? `<div>${Math.round(component.oc.files.template.size / 1024)} kb</div>`
: '<div>? Kb</div>'
: '';

return `<a href="${component.name}/${component.version}/~info">
<div id="component-${component.name}" class="componentRow row table${
isHidden ? ' hide' : ''
}">
isHidden ? ' hide' : ''
}">
<div class="title">
<p class="name">${component.name}</p>
<span class="description">${component.description}</span>
</div>
${componentState}
<div class="author">${component.author.name || ''}</div>
<div>${component.version}</div>
${extraColumn}
${remoteServerColumns}
${sizeColumn}
</div>
</a>`;
};
Expand All @@ -58,7 +69,8 @@ export default function componentsList(vm: VM): string {
<div class="title"></div>
<div class="author">Author</div>
<div>Latest version</div>
${extraColumn}
${remoteServerColumns}
${sizeColumn}
</div>
${vm.components.map(componentRow).join('')}
</div>`;
Expand Down

0 comments on commit e812294

Please sign in to comment.