mirror of
https://github.com/jakejarvis/jarv.is.git
synced 2025-07-03 19:06:40 -04:00
move some cruft from serverless API to client
This commit is contained in:
26
api/hits.ts
26
api/hits.ts
@ -5,9 +5,6 @@ import * as Tracing from "@sentry/tracing"; // eslint-disable-line @typescript-e
|
||||
import { VercelRequest, VercelResponse } from "@vercel/node";
|
||||
import { Client, query as q } from "faunadb";
|
||||
import fetch from "node-fetch";
|
||||
import pluralize from "pluralize";
|
||||
import numeral from "numeral";
|
||||
import { DateTime } from "luxon";
|
||||
import parser from "fast-xml-parser";
|
||||
import { decode } from "html-entities";
|
||||
|
||||
@ -68,7 +65,7 @@ export default async (req: VercelRequest, res: VercelResponse) => {
|
||||
}
|
||||
};
|
||||
|
||||
const incrementPageHits = async (slug: string | string[], client: Client) => {
|
||||
const incrementPageHits = async (slug: string | string[], client: Client): Promise<PageStats> => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const result = await client.query<any>(
|
||||
q.Let(
|
||||
@ -87,18 +84,11 @@ const incrementPageHits = async (slug: string | string[], client: Client) => {
|
||||
)
|
||||
);
|
||||
|
||||
// add formatted hits with comma and pluralized "hit(s)", simpler to do here than in browser
|
||||
const hits: PageStats = {
|
||||
...result.data,
|
||||
pretty_hits: numeral(result.data.hits).format("0,0"),
|
||||
pretty_unit: pluralize("hit", result.data.hits),
|
||||
};
|
||||
|
||||
// send client the *new* hit count
|
||||
return hits;
|
||||
return result.data;
|
||||
};
|
||||
|
||||
const getSiteStats = async (client: Client) => {
|
||||
const getSiteStats = async (client: Client): Promise<OverallStats> => {
|
||||
// get database and RSS results asynchronously
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const [feed, result] = await Promise.all<{ [key: string]: any }, any>([
|
||||
@ -123,13 +113,9 @@ const getSiteStats = async (client: Client) => {
|
||||
if (match) {
|
||||
p.title = decode(match.title);
|
||||
p.url = match.link;
|
||||
p.date = DateTime.fromRFC2822(match.pubDate).toISO();
|
||||
p.date = new Date(match.pubDate).toISOString();
|
||||
}
|
||||
|
||||
// it's easier to add comma-separated numbers and proper pluralization here on the backend
|
||||
p.pretty_hits = numeral(p.hits).format("0,0");
|
||||
p.pretty_unit = pluralize("hit", p.hits);
|
||||
|
||||
// add these hits to running tally
|
||||
stats.total.hits += p.hits;
|
||||
|
||||
@ -141,9 +127,5 @@ const getSiteStats = async (client: Client) => {
|
||||
return a.hits > b.hits ? -1 : 1;
|
||||
});
|
||||
|
||||
// do same prettification as above to totals
|
||||
stats.total.pretty_hits = numeral(stats.total.hits).format("0,0");
|
||||
stats.total.pretty_unit = pluralize("hit", stats.total.hits);
|
||||
|
||||
return stats;
|
||||
};
|
||||
|
@ -4,8 +4,6 @@ import * as Sentry from "@sentry/node";
|
||||
import * as Tracing from "@sentry/tracing"; // eslint-disable-line @typescript-eslint/no-unused-vars
|
||||
import { VercelRequest, VercelResponse } from "@vercel/node";
|
||||
import { encode } from "html-entities";
|
||||
import { DateTime } from "luxon";
|
||||
import numeral from "numeral";
|
||||
import { GraphQLClient } from "graphql-request";
|
||||
import { gql } from "graphql-tag";
|
||||
|
||||
@ -101,9 +99,6 @@ const fetchRepos = async (sort: string, limit: number): Promise<Repository[]> =>
|
||||
({ node: repo }: { [key: string]: Repository }) => ({
|
||||
...repo,
|
||||
description: encode(repo.description),
|
||||
stargazerCount_pretty: numeral(repo.stargazerCount).format("0,0"),
|
||||
forkCount_pretty: numeral(repo.forkCount).format("0,0"),
|
||||
pushedAt_relative: DateTime.fromISO(repo.pushedAt).toRelative({ locale: "en" }),
|
||||
})
|
||||
);
|
||||
|
||||
|
4
api/types/hits.d.ts
vendored
4
api/types/hits.d.ts
vendored
@ -4,15 +4,11 @@ type PageStats = {
|
||||
date?: string;
|
||||
slug: string;
|
||||
hits: number;
|
||||
pretty_hits: string;
|
||||
pretty_unit: string;
|
||||
};
|
||||
|
||||
type OverallStats = {
|
||||
total: {
|
||||
hits: number;
|
||||
pretty_hits?: string;
|
||||
pretty_unit?: string;
|
||||
};
|
||||
pages: PageStats[];
|
||||
};
|
||||
|
3
api/types/projects.d.ts
vendored
3
api/types/projects.d.ts
vendored
@ -7,9 +7,6 @@ type Repository = {
|
||||
name: string;
|
||||
};
|
||||
stargazerCount: number;
|
||||
stargazerCount_pretty?: string;
|
||||
forkCount: number;
|
||||
forkCount_pretty?: string;
|
||||
pushedAt: string;
|
||||
pushedAt_relative?: string;
|
||||
};
|
||||
|
@ -1,4 +1,5 @@
|
||||
import fetch from "cross-fetch";
|
||||
import numeral from "numeral";
|
||||
import * as queryString from "query-string";
|
||||
|
||||
// don't continue if there isn't a span#meta-hits element on this page
|
||||
@ -18,14 +19,17 @@ if (wrapper) {
|
||||
fetch(queryString.stringifyUrl({ url: "/api/hits/", query: { slug: slug } }))
|
||||
.then((response) => response.json())
|
||||
.then((data) => {
|
||||
if (typeof data.hits !== "undefined") {
|
||||
if (data.hits) {
|
||||
// finally inject the hits and hide the loading spinner
|
||||
const spinner = document.getElementById("hit-spinner");
|
||||
const counter = document.getElementById("hit-counter");
|
||||
|
||||
const hitsComma = numeral(data.hits).format("0,0");
|
||||
const hitsPlural = data.hits === 1 ? "hit" : "hits";
|
||||
|
||||
if (spinner) spinner.style.display = "none";
|
||||
if (counter) counter.appendChild(document.createTextNode(data.pretty_hits));
|
||||
wrapper.title = data.pretty_hits + " " + data.pretty_unit;
|
||||
if (counter) counter.appendChild(document.createTextNode(hitsComma));
|
||||
wrapper.title = hitsComma + " " + hitsPlural;
|
||||
} else {
|
||||
// something went horribly wrong, initiate coverup
|
||||
wrapper.style.display = "none";
|
||||
|
@ -1,9 +1,14 @@
|
||||
import fetch from "cross-fetch";
|
||||
import numeral from "numeral";
|
||||
import dayjs from "dayjs";
|
||||
import relativeTime from "dayjs/plugin/relativeTime.js";
|
||||
|
||||
// don't continue if there isn't a span#meta-hits element on this page
|
||||
const wrapper = document.getElementById("github-cards");
|
||||
|
||||
if (wrapper) {
|
||||
dayjs.extend(relativeTime);
|
||||
|
||||
fetch("/api/projects/?top")
|
||||
.then((response) => response.json())
|
||||
.then((data) => {
|
||||
@ -24,7 +29,7 @@ if (wrapper) {
|
||||
html += `
|
||||
<div class="repo-meta">
|
||||
<svg viewBox="0 0 16 16" height="16" width="16"><path fill-rule="evenodd" d="M8 .25a.75.75 0 01.673.418l1.882 3.815 4.21.612a.75.75 0 01.416 1.279l-3.046 2.97.719 4.192a.75.75 0 01-1.088.791L8 12.347l-3.766 1.98a.75.75 0 01-1.088-.79l.72-4.194L.818 6.374a.75.75 0 01.416-1.28l4.21-.611L7.327.668A.75.75 0 018 .25zm0 2.445L6.615 5.5a.75.75 0 01-.564.41l-3.097.45 2.24 2.184a.75.75 0 01.216.664l-.528 3.084 2.769-1.456a.75.75 0 01.698 0l2.77 1.456-.53-3.084a.75.75 0 01.216-.664l2.24-2.183-3.096-.45a.75.75 0 01-.564-.41L8 2.694v.001z"></path></svg>
|
||||
<span>${repo.stargazerCount_pretty}</span>
|
||||
<span>${numeral(repo.stargazerCount).format("0,0")}</span>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
@ -32,13 +37,13 @@ if (wrapper) {
|
||||
html += `
|
||||
<div class="repo-meta">
|
||||
<svg viewBox="0 0 16 16" height="16" width="16"><path fill-rule="evenodd" d="M5 3.25a.75.75 0 11-1.5 0 .75.75 0 011.5 0zm0 2.122a2.25 2.25 0 10-1.5 0v.878A2.25 2.25 0 005.75 8.5h1.5v2.128a2.251 2.251 0 101.5 0V8.5h1.5a2.25 2.25 0 002.25-2.25v-.878a2.25 2.25 0 10-1.5 0v.878a.75.75 0 01-.75.75h-4.5A.75.75 0 015 6.25v-.878zm3.75 7.378a.75.75 0 11-1.5 0 .75.75 0 011.5 0zm3-8.75a.75.75 0 100-1.5.75.75 0 000 1.5z"></path></svg>
|
||||
<span>${repo.forkCount_pretty}</span>
|
||||
<span>${numeral(repo.forkCount).format("0,0")}</span>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
html += `
|
||||
<div class="repo-meta">
|
||||
<span title="${repo.pushedAt}">Updated ${repo.pushedAt_relative}</span>
|
||||
<span title="${dayjs(repo.pushedAt).format("MMM D, YYYY h:mm A")}">Updated ${dayjs(repo.pushedAt).fromNow()}</span>
|
||||
</div>`;
|
||||
|
||||
const div = document.createElement("div");
|
||||
|
@ -12,7 +12,7 @@ import imageminSvgo from "imagemin-svgo";
|
||||
|
||||
gulp.task("default", gulp.series(
|
||||
clean,
|
||||
npx("webpack", ["--mode", "production", "--progress", "profile"]),
|
||||
npx("webpack", ["--mode", "production"]),
|
||||
npx("hugo"),
|
||||
gulp.parallel(
|
||||
optimizeHtml,
|
||||
|
@ -35,6 +35,7 @@
|
||||
"@sentry/node": "^6.8.0",
|
||||
"@sentry/tracing": "^6.8.0",
|
||||
"cross-fetch": "3.1.4",
|
||||
"dayjs": "1.10.6",
|
||||
"dotenv": "^10.0.0",
|
||||
"fast-xml-parser": "^3.19.0",
|
||||
"faunadb": "^4.3.0",
|
||||
@ -42,11 +43,9 @@
|
||||
"graphql-request": "^3.4.0",
|
||||
"graphql-tag": "^2.12.5",
|
||||
"html-entities": "^2.3.2",
|
||||
"luxon": "^1.27.0",
|
||||
"modern-normalize": "1.1.0",
|
||||
"node-fetch": "^2.6.1",
|
||||
"numeral": "^2.0.6",
|
||||
"pluralize": "^8.0.0",
|
||||
"query-string": "7.0.1",
|
||||
"twemoji": "13.1.0",
|
||||
"twemoji-emojis": "14.1.0"
|
||||
@ -55,10 +54,8 @@
|
||||
"@babel/cli": "^7.14.5",
|
||||
"@babel/core": "^7.14.6",
|
||||
"@babel/preset-env": "^7.14.7",
|
||||
"@types/luxon": "^1.27.1",
|
||||
"@types/node-fetch": "^2.5.11",
|
||||
"@types/numeral": "^2.0.1",
|
||||
"@types/pluralize": "^0.0.29",
|
||||
"@types/twemoji": "^12.1.1",
|
||||
"@typescript-eslint/eslint-plugin": "^4.28.2",
|
||||
"@typescript-eslint/parser": "^4.28.2",
|
||||
|
25
yarn.lock
25
yarn.lock
@ -1176,11 +1176,6 @@
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/luxon@^1.27.1":
|
||||
version "1.27.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/luxon/-/luxon-1.27.1.tgz#aceeb2d5be8fccf541237e184e37ecff5faa9096"
|
||||
integrity sha512-cPiXpOvPFDr2edMnOXlz3UBDApwUfR+cpizvxCy0n3vp9bz/qe8BWzHPIEFcy+ogUOyjKuCISgyq77ELZPmkkg==
|
||||
|
||||
"@types/mdast@^3.0.0":
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-3.0.4.tgz#8ee6b5200751b6cadb9a043ca39612693ad6cb9e"
|
||||
@ -1226,11 +1221,6 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0"
|
||||
integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==
|
||||
|
||||
"@types/pluralize@^0.0.29":
|
||||
version "0.0.29"
|
||||
resolved "https://registry.yarnpkg.com/@types/pluralize/-/pluralize-0.0.29.tgz#6ffa33ed1fc8813c469b859681d09707eb40d03c"
|
||||
integrity sha512-BYOID+l2Aco2nBik+iYS4SZX0Lf20KPILP5RGmM1IgzdwNdTs0eebiFriOPcej1sX9mLnSoiNte5zcFxssgpGA==
|
||||
|
||||
"@types/q@^1.5.1":
|
||||
version "1.5.5"
|
||||
resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.5.tgz#75a2a8e7d8ab4b230414505d92335d1dcb53a6df"
|
||||
@ -3090,6 +3080,11 @@ d@1, d@^1.0.1:
|
||||
es5-ext "^0.10.50"
|
||||
type "^1.0.1"
|
||||
|
||||
dayjs@1.10.6:
|
||||
version "1.10.6"
|
||||
resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.10.6.tgz#288b2aa82f2d8418a6c9d4df5898c0737ad02a63"
|
||||
integrity sha512-AztC/IOW4L1Q41A86phW5Thhcrco3xuAA+YX/BLpLWWjRcTj5TOt/QImBLmCKlrF7u7k47arTnOyL6GnbG8Hvw==
|
||||
|
||||
debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.9:
|
||||
version "2.6.9"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
|
||||
@ -6590,11 +6585,6 @@ lru_map@^0.3.3:
|
||||
resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.3.3.tgz#b5c8351b9464cbd750335a79650a0ec0e56118dd"
|
||||
integrity sha1-tcg1G5Rky9dQM1p5ZQoOwOVhGN0=
|
||||
|
||||
luxon@^1.27.0:
|
||||
version "1.27.0"
|
||||
resolved "https://registry.yarnpkg.com/luxon/-/luxon-1.27.0.tgz#ae10c69113d85dab8f15f5e8390d0cbeddf4f00f"
|
||||
integrity sha512-VKsFsPggTA0DvnxtJdiExAucKdAnwbCCNlMM5ENvHlxubqWd0xhZcdb4XgZ7QFNhaRhilXCFxHuoObP5BNA4PA==
|
||||
|
||||
make-dir@^1.0.0, make-dir@^1.2.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c"
|
||||
@ -7844,11 +7834,6 @@ plur@^3.0.1:
|
||||
dependencies:
|
||||
irregular-plurals "^2.0.0"
|
||||
|
||||
pluralize@^8.0.0:
|
||||
version "8.0.0"
|
||||
resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-8.0.0.tgz#1a6fa16a38d12a1901e0320fa017051c539ce3b1"
|
||||
integrity sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==
|
||||
|
||||
pngquant-bin@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/pngquant-bin/-/pngquant-bin-6.0.0.tgz#aff0d7e61095feb96ced379ad8c7294ad3dd1712"
|
||||
|
Reference in New Issue
Block a user