I tend to automate the most basic tasks because it’s more fun than copy-pasting. If I need to do something more than ~5x I’m like to write a script for it.
This time I was writing a blog post comparing some Flutter packages and had to generate badges for each package. I wanted to show stars, rating, popularity and such and found that copy-pasting this for each single package was tedious.
In the end, combined with writing this article about it I didn’t save any time for sure 😂 but it was a lot more fun. Also, I learned about CORS proxies (see bottom).
This is so lightweight I won’t even link to something outside but just drop it here. It uses jquery and a few lines of code to call the dart.pub API. Here it is (or check the jsFiddle):
function setOutput(html) {
$('#code-output').text(html);
$('#rendered-ouput').html(html);
}
function renderOutput(packageName, githubName) {
const html = `
<a href="https://github.com/${githubName}" target="_blank">
<img decoding="async" src="https://img.shields.io/github/stars/${githubName}.svg">
</a><br>
<a href="https://pub.dev/packages/${packageName}/score" target="_blank">
<img decoding="async" src="https://badges.bar/${packageName}/likes">
</a><br>
<a href="https://pub.dev/packages/${packageName}/score" target="_blank">
<img decoding="async" src="https://badges.bar/${packageName}/popularity">
</a><br>
<a href="https://pub.dev/packages/${packageName}/score" target="_blank">
<img decoding="async" src="https://badges.bar/${packageName}/pub%20points">
</a>
`.trim();
setOutput(html);
}
function renderError(error) {
setOutput(error.toString());
}
function run() {
const packageName = $('#pubdev')[0].value;
const url = `https://pub.dev/api/packages/${packageName}`;
const proxyUrl = "https://api.allorigins.win/get?url=" + encodeURIComponent(url);
$.ajax({
url: proxyUrl,
method: "GET",
success: function(response) {
const data = JSON.parse(response.contents);
if (data.error) {
renderError(data.error.message);
return;
}
const github = data.latest.pubspec.homepage;
const githubName = github.replace('https://github.com/', '').replace(//$/, '');
renderOutput(packageName, githubName);
},
error: function(err) {
renderError(err);
}
});
}
Input
pub.dev package name
Render it!
Html
Rendered
The code
Explaining it
As mentioned, building this I found that pub.dev has an open API! You can GET any package data by calling https://pub.dev/api/packages/
Secondly, calling this API from inside a page of my own, such as this, I hit a CORS issue. That is, the pub.dev server isn’t sending back the headers required to tell my browser that this source is intended for my browser. What Chrome then does is that it simply shuts it down. It looks like this:
Getting a CORS error requesting 3rd party URL
It turns out many kind people out there has provided us with free solutions for simply proxying our request and adding the headers required!
One such service is https://allorigins.win/. How do you use it? Simply call their service and pass your URL as a query parameter:
const actualUrl = `https://pub.dev/api/packages/${packageName}`
const proxyUrl = "https://api.allorigins.win/get?url=" + encodeURIComponent(actualUrl)
You can then inspect the request and see that the allorigins proxy has added the headers we need.
CORS headers added by allorigins.win proxy service
Not faster but more fun
Using these tiny jsFiddle’s, a proxy service, open API endpoints and a bit of jQuery it’s really fast to script away boring repetitive tasks.
Really, I need to learn how to focus at the task in front of me instead of throwing myself over the next shiny thing 🙂 see you next time!