Devblog #6 - The anniversary update ๐
Introductionโ
This devblog marks the 1 year devblog anniversary ๐
Among other things this devblog talks about the new MultiReport
, how the unit tests randomly broke (again) and the new Algolia Search integration.
This devblog is about the packageanalyzer
project.
A framework to introspect Node.js packages.
Please find a short introduction and the motivation for this project here.
Adding MultiReport
functionalityโ
The main new featue that happened since last time was the addition of a MultiReport
.
The MultiReport
lets you inspect 2 or more packages at the same time.
Whyโ
Security is a central tenet of the packageanalyzer
.
As such there needs to be functionality that let's you directly highlight changes between 2 versions of the same package. E.g. dependency changes, maintainer changes etc. To support this use case the packageanalyzer
needs to be able to inspect multiple packages at the same time.
Up until now you could only inspect 1 package at a time. While you could already specify and run different reports in 1 go, they would be totally isolated and independent from each other.
With the MultiReport
it is now possible to inspect 2 or more packages at the same time in a single Report
.
The implementation was actually fairly easy, since the Report
feature already existed (although only for 1 package at a time) all that was needed was to call this logic in a loop, to resolve the dependency tree for each specified package and then hand over all resolved dependency trees to the report
method.
To improve the developer experience the report
method signature was adapted. Up until now the signature looked like this:
report(pkg: Package, context: IReportContext): Promise<void>;
The 1st argument was the resolved dependency tree and the 2nd argument contained a context
object, which housed stdout
and stderr
for CLI output.
To accommodate multiple dependency trees the context
was made the first argument followed then by the dependency tree(s):
report(context: IReportContext, pkg1: Package, /*...,*/ pkgN: Package): Promise<void>;
This way it's more inline with existing JavaScript API's that also provide arbitrary number of arguments, like Function.prototype.bind()
bind(thisArg);
bind(thisArg, arg1, /* โฆ, */ argN);
Usageโ
To use the new MultiReport
you just need to specify the package names in the entries
attribute for which you want to resolve the dependency tree and in the callback
you can then consume the corresponding resolved dependency trees.
const multiReport = new MultiReport({
entries: [
[`react`, `18.2.0`],
[`react`, `17.0.2`]
],
callback: async (
_ctx,
pkg1 /* react@18.2.0 dependency tree */,
pkg2 /* react@17.0.2 dependency tree */
) => {
//todo do something with pkg1 & pkg2
}
});
Unit Test fixesโ
As is tradition by now, the Unit Tests broke again randomly: Here it checks the update command for the latest version of React.
The Unit Test is set to a specific date, so no matter when the test is run, it should display 217 days ago and the latest version should be 17.0.2 however the test revealed a negativ time span with the latest version being 18.2.0 which was released only 2 months ago.
This shouldn't happen as all test data is stored locally. If it was done properly... turns out it wasn't.
This specific Unit Test was still accessing live data from NPM, that's why it was able to (correctly) identify the latest version as 18.2.0.
Live NPM data in Unit Tests used to be the cause for numerous random test failures, to prevent such errors in the future a safety mechanism was put into place to write to stderr
in case live NPM data is accessed in a test run. Since stderr
gets snapshot tested too, it will be easily visible if live NPM data was accessed.
However nothing was written to stderr
in this case because the live NPM data was accessed via custom logic which circumvented this safety mechanism.
After removing this custom logic to follow the standard way, there was now a message in stderr
warning that live NPM data was used:
All that was needed now to fix the issue was to provide the correct test data by specifying the correct Provider
for the Unit Test:
//set unit test provider
command.beforeProcess = report => (report.provider = provider);
However after providing the correct test data, the test still failed: Turns out that the existing "correct" snapshot is actually also wrong as it too used live NPM data when it was created. The correct version number when using the test data is actually 16.8.6.
After updating the snapshots, the Unit Test ran fine again, hopefully this was the last test breakage due to live NPM data usage in the Unit Tests ๐ค
Documentationโ
The documentation also received some updates:
Algolia Integrationโ
To help discoverability of the documentation I decided to add Algolia's DocSearch. Up until now you couldn't search the documentation.
As the documentation is powered by Docusaurus it was super easy to add since it comes with Algolia support out of the box.
All that was needed was:
- Sign up for Algolia DocSearch (It's free for Open Source Projects)
- Add an
algolia
section to the docusaurus conf:
module.exports = {
// ...
themeConfig: {
// ...
algolia: {
appId: "YOUR_APP_ID",
apiKey: "YOUR_SEARCH_API_KEY",
indexName: "YOUR_INDEX_NAME"
}
}
};
And with that you've added search to your documentation:
The search is also responsive with light/dark theme support out of the box ๐
Up to date documentationโ
As I added new features (like the new MultiReport
and refactored more and more code, the code examples in the documentation ran out of sync. Now they should be up to date again โ๏ธ
Next Stepsโ
Employ a steady cadence of devblogs. Writing a devblog is a great way to reflect on the work that was done. More often than not I would revisited a newly added feature because when writing about it, it turned out to be too complex to use.
When you are working on a feature you are totally immersed and everything seems logical but if you re-visit it again in the future, e.g. to write about in a devblog or to write documentation for it you get a much more sober view of the work you did. Chances are if you write about it and it feels complex, it most likely is. Writing about it is a good reality check.
The next big planned feature is parsing the respective .tar
archive of a package to make the individual files available for processing.
For example it would allow running a static code analyzer on the source code or inspecting the file that was referenced in the postinstall
command. Coupled with the newly added MultiReport
this allows for more elaborate analysis scenarios.