Scrivere un plugin xbar in Javascript
Come progetto del fine settimana volevo scrivere un semplice plugin per xbar, un'applicazione in cui mi sono imbattuto di recente. xbar stesso è scritto nel linguaggio di programmazione "Go" e utilizza "Wails" come servizio sottostante per consentire agli sviluppatori di scrivere voci di menu personalizzate per la barra dei menu in macOS (sì, attualmente è limitato solo a macOS).
La cosa bella di xbar è che supporta un'ampia varietà di linguaggi di programmazione, che include anche Javascript. Come sviluppatore web, volevo quindi vedere quanto fosse facile scrivere un plug-in personalizzato che si collegasse a Plausible.io, il mio servizio di analisi rispettoso della privacy. L'obiettivo è eseguire il rendering di tutti gli utenti attuali che sono attualmente su questa app Web. Al momento della stesura, la richiesta pull è ancora in fase di revisione.
Configurazione di base di xbar
xbar può essere semplicemente scaricato e installato sul tuo Mac. Una volta avviato per la prima volta, è possibile utilizzare una schermata che contiene tutti i plug-in scaricabili e pubblicati per ottenere il plug-in che si desidera avere.
Il processo di installazione copia semplicemente il codice sorgente del plugin (un singolo file per plugin) in una cartella speciale, dalla quale xbar legge tutti i plugin attualmente installati. Per iniziare a scrivere il tuo plugin, devi semplicemente creare un file nella directory e iniziare a hackerare. Pulito!
convenzione del nome del file xbar
Il nome del file è composto da tre parti, tutte separate da un punto.
- il tuo nome univoco del plugin
- l'intervallo di tempo in cui viene eseguito il codice, simile a un lavoro CRON
- il suffisso file comune
plausible.1m.js
Codificare un plugin xbar in JS
Ora sei pronto per iniziare a programmare! Per prima cosa includi la direttiva shebang richiesta per dire a xbar dove dovrebbe essere trovata l'istanza del nodo.
#!/usr/bin/env /usr/local/bin/node
La parte successiva è quindi l'aggiunta di alcuni metadati. Naturalmente, per lo sviluppo locale questo può essere omesso, ma ecco cosa sto usando per il plug-in plausibile.
// Metadata allows your plugin to show up in the app, and website.
//
// <xbar.title>Plausible Tracker</xbar.title>
// <xbar.version>v1.0</xbar.version>
// <xbar.author>Tom Schönmann</xbar.author>
// <xbar.author.github>flaming-codes</xbar.author.github>
// <xbar.desc>See who's on your site at-a-glance.</xbar.desc>
// <xbar.dependencies>node</xbar.dependencies>
// <xbar.abouturl>https://flaming.codes</xbar.abouturl>
// <xbar.image>https://raw.githubusercontent.com/flaming-codes/xbar-plausible-stats/main/plausible-icon-36-36-144.png</xbar.image>
E questo è tutto ciò che è necessario per l'esecuzione del tuo plug-in. Ora hai una tela in cui puoi codificare in puro Javascript, eseguito dall'istanza Node.js dell'utente. Ciò significa che abbiamo accesso a tutti i pacchetti Node principali, come "https". Per il mio caso d'uso, questo è tutto ciò di cui ho bisogno, poiché il tracciamento degli utenti richiede semplicemente un recupero dall'API Plausible.io.
I seguenti pezzi di codice mostrano la parte più rilevante di cui penso valga la pena parlare. Il codice completo è disponibile nel relativo repository pubblico, link nell'addendum alla fine di questa pagina.
// Here you see how to make network
// requests with 'https'-only.
// This is a native node-lib that
// works w/ data streams, as you'll see.
const https = require("https");
// Those have to edited by the
// user directly in the file,
// after it has been downloaded
// (aka installed)!
const SITE_ID = "";
const API_KEY = "";
// ... other code ...
async function fetcher() {
return new Promise((resolve, reject) => {
let body = "";
const request = {
host: "plausible.flaming.codes",
path: `/api/v1/stats/realtime/visitors?site_id=${SITE_ID}`,
method: "GET",
headers: {
Authorization: `Bearer ${API_KEY}`,
},
};
try {
const req = https.get(request, (res) => {
res.on("data", (data) => {
body += data;
});
res.on("end", () => {
resolve(JSON.parse(body));
});
});
req.on("error", (error) => {
console.error(error);
});
req.end();
} catch (error) {
reject(error);
}
});
}
// I've implemented an array of tuples
// that hold an icon + count threshold
// when to active it.
// The first entry doesn't render a
// string (which can be direclty used),
// but rather a mapping that results in
// the following code:
//
// `image="..." font=Menlo color=white`
//
// This is a special syntax that tells
// xbar to render a base64 image w/
// a custom font and color.
//
// 'plausibleIconWhite' is just the string
// for the base64-image.
const stepIcons = [
[0, `${plausibleIconWhite} Menlo white`, "image font color"],
[5, "💫"],
[10, "⭐️"],
[50, "🌟"],
[100, "⚡️"],
[500, "💥"],
];
// Actually rendering stuff in xbar
// is super simple - just output it
// with console.log(...).
//
// As you'll see, '---' define
// separator. The first log-call
// gets rendered as acutal menu item.
const linksMenu = [
"---",
`🔮 Open dashboard | href=https://plausible.flaming.codes/${SITE_ID}`,
`🔥 Made by flaming.codes | href=https://flaming.codes`,
];
function renderError(props) {
const { error } = props;
const output = [
"❔",
"---",
"No data accessible",
"Please check your user data",
...linksMenu,
];
console.log(output.join("\n"));
}
// Finally, I defined a single function
// where everything starts. This function
// just gets called to kick everyting off.
// Plain JS, it's that simple.
async function render() {
const { data, error } = await fetcher()
.then((data) => ({ data }))
.catch((error) => ({ error }));
if (data >= 0) return renderData({ data });
if (error) return renderError({ error });
}
render();
La codifica per xbar è facile
L'intero processo mi ha richiesto alcune ore per essere completato, principalmente controllando l'API da xbar e giocando con diverse configurazioni per lo stile. Tutto sommato, scrivere un semplice plugin come questo non è davvero un grande sforzo che è davvero divertente da fare. Se hai qualche ora libera, dovresti provare anche tu!
Penso che ciò che parla di più per xbar sia l'opportunità di scripting che questo sviluppo flessibile e veloce consente. Puoi scrivere tracker personalizzati per le tue configurazioni cloud o servizi di analisi, in modo che le metriche siano tutte visibili a colpo d'occhio nella barra dei menu in macOS. Mi piace!