From ccc33ec989fb56597a2ed4b7e60d0c73bc0127cd Mon Sep 17 00:00:00 2001 From: tudor Date: Tue, 31 Mar 2026 18:18:28 +0200 Subject: [PATCH 1/4] initial CTA npm --- docs/.vitepress/config.mts | 4 ++ docs/components/starCount.ts | 20 ++++++ docs/downloadCount.data.ts | 7 ++ docs/index.md | 129 ++++++++++++++++++++++++++--------- 4 files changed, 129 insertions(+), 31 deletions(-) create mode 100644 docs/downloadCount.data.ts diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts index 3ac2ed7e6..5bfb0c00d 100644 --- a/docs/.vitepress/config.mts +++ b/docs/.vitepress/config.mts @@ -85,6 +85,10 @@ export default defineConfig({ text: 'Star on GitHub', link: 'https://github.com/electric-sql/pglite', }, + { + text: 'Get from NPM', + link: 'https://www.npmjs.com/package/@electric-sql/pglite', + }, ], sidebar: [ { diff --git a/docs/components/starCount.ts b/docs/components/starCount.ts index 99db10725..dd5ca16da 100644 --- a/docs/components/starCount.ts +++ b/docs/components/starCount.ts @@ -43,3 +43,23 @@ export async function fetchStarCount(currentCount) { return currentCount || FALLBACK_INITIAL_COUNT } + +const FALLBACK_NPMJS_DWN_INITIAL_COUNT = 6842562 + +export async function downloadCount(currentDownloadCount) { + const ttl = 3600 // 1 hour + return localStorageCache('downloadCount', ttl, async () => { + return await fetchNpmJsDownloadCount(currentDownloadCount) + }) +} + +export async function fetchNpmJsDownloadCount(currentCount) { + const resp = await fetch('https://api.npmjs.org/downloads/point/last-week/@electric-sql/pglite') + + if (resp.ok) { + const data = await resp.json() + return data.downloads + } + + return currentCount || FALLBACK_NPMJS_DWN_INITIAL_COUNT +} \ No newline at end of file diff --git a/docs/downloadCount.data.ts b/docs/downloadCount.data.ts new file mode 100644 index 000000000..baeb2dd18 --- /dev/null +++ b/docs/downloadCount.data.ts @@ -0,0 +1,7 @@ +import { fetchNpmJsDownloadCount } from './components/starCount.ts' + +export default { + async load() { + return await fetchNpmJsDownloadCount() + }, +} diff --git a/docs/index.md b/docs/index.md index 821cb0cc8..b555c57c9 100644 --- a/docs/index.md +++ b/docs/index.md @@ -13,6 +13,9 @@ hero: - theme: alt text: Star on GitHub link: https://github.com/electric-sql/pglite + - theme: alt + text: Get from NPM + link: https://www.npmjs.com/package/@electric-sql/pglite features: - title: Lightweight @@ -28,41 +31,90 @@ import { onMounted } from 'vue' import { defineClientComponent } from 'vitepress' import { VPHomeHero } from 'vitepress/theme' import { data as initialStarCount } from './count.data.ts' -import { starCount } from './components/starCount.ts' +import { data as initialDownloadCount } from './downloadCount.data.ts' +import { starCount, downloadCount } from './components/starCount.ts' const Repl = defineClientComponent(() => { return import('./components/Repl.vue') }) -onMounted(async () => { - if (typeof window !== 'undefined' && document.querySelector) { - const linkEl = document.querySelector('.action a[href="https://github.com/electric-sql/pglite"]') - let countEl = linkEl.querySelector('.count') +function toShortDecimal(x) { + return x.toLocaleString('en-US', { + // add suffixes for thousands, millions, and billions + // the maximum number of decimal places to use + maximumFractionDigits: 1, + // specify the abbreviations to use for the suffixes + notation: 'compact', + compactDisplay: 'short' + }); +} + +async function renderGitHub() { + const linkEl = document.querySelector('.action a[href="https://github.com/electric-sql/pglite"]') + let countEl = linkEl.querySelector('.count') + + if (!countEl) { + countEl = document.createElement('span') + countEl.classList.add('count') + countEl.innerText = `(${toShortDecimal(initialStarCount)})`; + + const icon = document.createElement('span') + icon.classList.add('vpi-social-github') + linkEl.prepend(icon) + } - if (!countEl) { - countEl = document.createElement('span') - countEl.classList.add('count') - countEl.innerText = `( ${initialStarCount.toLocaleString()} )`; - - const icon = document.createElement('span') - icon.classList.add('vpi-social-github') - linkEl.prepend(icon) + linkEl.append(countEl) + + const count = await starCount(initialStarCount) + + let currentCount = Math.max(count - 15, initialStarCount) + const animateCount = () => { + currentCount += 1; + if (currentCount >= count) { + currentCount = count; + clearInterval(intervalId); } + + countEl.innerText = `(${toShortDecimal(currentCount)})`; + }; + const intervalId = setInterval(animateCount, 64); +} + +async function renderNpmJs() { + const linkEl = document.querySelector('.action a[href="https://www.npmjs.com/package/@electric-sql/pglite"]') + let countEl = linkEl.querySelector('.count') - linkEl.append(countEl) - - const count = await starCount(initialStarCount) - - let currentCount = Math.max(count - 15, initialStarCount) - const animateCount = () => { - currentCount += 1; - if (currentCount >= count) { - currentCount = count; - clearInterval(intervalId); - } - countEl.innerText = `( ${currentCount.toLocaleString()} )`; - }; - const intervalId = setInterval(animateCount, 64); + if (!countEl) { + countEl = document.createElement('span') + countEl.classList.add('count') + countEl.innerText = `(${toShortDecimal(initialDownloadCount)})`; + + const icon = document.createElement('span') + icon.classList.add('vpi-social-npm') + linkEl.prepend(icon) + } + + linkEl.append(countEl) + + const count = await downloadCount(initialDownloadCount) + + let currentCount = Math.max(count - 15, initialDownloadCount) + const animateCount = () => { + currentCount += 1; + if (currentCount >= count) { + currentCount = count; + clearInterval(intervalId); + } + + countEl.innerText = `(${toShortDecimal(currentCount)})`; + }; + const intervalId = setInterval(animateCount, 64); +} + +onMounted(async () => { + if (typeof window !== 'undefined' && document.querySelector) { + renderGitHub() + renderNpmJs() } }); @@ -73,17 +125,32 @@ onMounted(async () => { display: flex; align-items: center; } + .actions a[href="https://www.npmjs.com/package/@electric-sql/pglite"] { + display: flex; + align-items: center; + } .actions a[href="https://github.com/electric-sql/pglite"] .vpi-social-github { display: block; - width: 1.42rem; - height: 1.42rem; - margin: 0 0.5rem 0 0; + width: 1.22rem; + height: 1.22rem; + margin: 0 0.3rem 0 0; position: relative; } + .actions a[href="https://www.npmjs.com/package/@electric-sql/pglite"] .vpi-social-npm { + display: block; + width: 1.22rem; + height: 1.22rem; + margin: 0 0.3rem 0 0; + position: relative; + } .actions a[href="https://github.com/electric-sql/pglite"] .count { margin-left: 0.25rem; - min-width: 55px; + min-width: 45px; } + .actions a[href="https://www.npmjs.com/package/@electric-sql/pglite"] .count { + margin-left: 0.25rem; + min-width: 45px; + }