Skip to content

Commit

Permalink
Update view model logic to use data persisted in SQLite
Browse files Browse the repository at this point in the history
  • Loading branch information
danlivings-dxw committed Sep 27, 2024
1 parent f452480 commit d46db7a
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 132 deletions.
10 changes: 5 additions & 5 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { createServer } from "http";
import nunjucks from "nunjucks";
import { readFromJsonFile, mapRepoFromStorageToUi } from "./utils/index.js";
import { mapRepoFromStorageToUi } from "./utils/index.js";
import { getQueryParams } from "./utils/queryParams.js";
import { sortByType } from "./utils/sorting.js";
import { TowtruckDatabase } from "./db/index.js";

nunjucks.configure({
autoescape: true,
Expand All @@ -17,10 +18,9 @@ const httpServer = createServer(async (request, response) => {
return response.end();
}

const [ persistedRepoData, persistedLifetimeData ] = await Promise.all([
readFromJsonFile("./data/repos.json"),
readFromJsonFile("./data/lifetimes.json"),
]);
const db = new TowtruckDatabase();
const persistedRepoData = db.getAllRepositories();
const persistedLifetimeData = db.getAllDependencies();

const reposForUi = mapRepoFromStorageToUi(persistedRepoData, persistedLifetimeData);

Expand Down
46 changes: 17 additions & 29 deletions utils/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { readFile } from "fs/promises";
import { differenceInYears, formatDistance, formatDistanceToNow, startOfToday } from "date-fns";
import { getDependencyEndOfLifeDate, getDependencyState } from "./endOfLifeDateApi/index.js";

Expand Down Expand Up @@ -64,7 +63,7 @@ const defaultIcon = "bx-question-mark";
* @returns {UiDependency}
*/
export const mapDependencyFromStorageToUi = (dependency, persistedLifetimes) => {
const lifetimes = persistedLifetimes.lifetimes.find((item) => item.dependency === dependency.name);
const lifetimes = Object.entries(persistedLifetimes).find(([name]) => name === dependency.name)?.[1];

const state = lifetimes === undefined ? "unknown" : getDependencyState(dependency, lifetimes.lifetimes);
const latestVersion = lifetimes?.lifetimes[0]?.latest;
Expand Down Expand Up @@ -139,49 +138,37 @@ export const hashToTailwindColor = (str) => {
* @returns {RepoData}
*/
export const mapRepoFromStorageToUi = (persistedData, persistedLifetimes) => {
const mappedRepos = persistedData.repos.map((repo) => {
const newDate = new Date(repo.updatedAt).toLocaleDateString();
const dependencies = repo.dependencies.map((dependency) => mapDependencyFromStorageToUi(dependency, persistedLifetimes));
const mappedRepos = Object.entries(persistedData).map(([, repo]) => {
const newDate = new Date(repo.main.updatedAt).toLocaleDateString();
const dependencies = repo.main.dependencies.map((dependency) => mapDependencyFromStorageToUi(dependency, persistedLifetimes));

const mostRecentPrOpenedAt = repo.mostRecentPrOpenedAt && formatDistanceToNow(repo.mostRecentPrOpenedAt, { addSuffix: true });
const oldestOpenPrOpenedAt = repo.oldestOpenPrOpenedAt && formatDistanceToNow(repo.oldestOpenPrOpenedAt, { addSuffix: true });
const mostRecentIssueOpenedAt = repo.mostRecentIssueOpenedAt && formatDistanceToNow(repo.mostRecentIssueOpenedAt, { addSuffix: true });
const oldestOpenIssueOpenedAt = repo.oldestOpenIssueOpenedAt && formatDistanceToNow(repo.oldestOpenIssueOpenedAt, { addSuffix: true });
const mostRecentPrOpenedAt = repo.main.mostRecentPrOpenedAt && formatDistanceToNow(repo.main.mostRecentPrOpenedAt, { addSuffix: true });
const oldestOpenPrOpenedAt = repo.main.oldestOpenPrOpenedAt && formatDistanceToNow(repo.main.oldestOpenPrOpenedAt, { addSuffix: true });
const mostRecentIssueOpenedAt = repo.main.mostRecentIssueOpenedAt && formatDistanceToNow(repo.main.mostRecentIssueOpenedAt, { addSuffix: true });
const oldestOpenIssueOpenedAt = repo.main.oldestOpenIssueOpenedAt && formatDistanceToNow(repo.main.oldestOpenIssueOpenedAt, { addSuffix: true });

const languageColor = hashToTailwindColor(repo.language);
const languageColor = hashToTailwindColor(repo.main.language);

return {
...repo,
...repo.main,
updatedAt: newDate,
updatedAtISO8601: repo.updatedAt,
updatedAtISO8601: repo.main.updatedAt,
dependencies,
mostRecentPrOpenedAt,
mostRecentPrOpenedAtISO8601: repo.mostRecentPrOpenedAt,
mostRecentPrOpenedAtISO8601: repo.main.mostRecentPrOpenedAt,
oldestOpenPrOpenedAt,
oldestOpenPrOpenedAtISO8601: repo.oldestOpenPrOpenedAt,
oldestOpenPrOpenedAtISO8601: repo.main.oldestOpenPrOpenedAt,
mostRecentIssueOpenedAt,
mostRecentIssueOpenedAtISO8601: repo.mostRecentIssueOpenedAt,
mostRecentIssueOpenedAtISO8601: repo.main.mostRecentIssueOpenedAt,
oldestOpenIssueOpenedAt,
oldestOpenIssueOpenedAtISO8601: repo.oldestOpenIssueOpenedAt,
oldestOpenIssueOpenedAtISO8601: repo.main.oldestOpenIssueOpenedAt,
languageColor,
};
});

const totalRepos = mappedRepos.length;

return { ...persistedData, repos: mappedRepos, totalRepos };
};

/**
* Reads data from a JSON file
* @param {string} filePath - The path to the file to read from
* @returns {any}
*/
export const readFromJsonFile = async (filePath) => {
const json = await readFile(filePath, { encoding: "utf-8" });
const persistedData = JSON.parse(json);

return persistedData;
return { org: Object.entries(persistedData)[0][1].owner, repos: mappedRepos, totalRepos };
};

/**
Expand Down Expand Up @@ -226,6 +213,7 @@ export const readFromJsonFile = async (filePath) => {
*/
export const mapRepoFromApiForStorage = (repo) => ({
name: repo.name,
owner: repo.owner.login,
description: repo.description,
htmlUrl: repo.html_url,
apiUrl: repo.url,
Expand Down
204 changes: 106 additions & 98 deletions utils/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,27 @@ import { formatDistanceToNow } from "date-fns";

describe("mapRepoFromStorageToUi", () => {
it("converts ISO8601 timestamps to human-readable forms", () => {
const storedRepos = [
{
name: "repo1",
description: "description1",
updatedAt: "2021-01-01T00:00:00Z",
htmlUrl: "http://url.com/repo1",
apiUrl: "http://api.com/repo1",
pullsUrl: "http://api.com/repo1/pulls",
issuesUrl: "http://api.com/repo1/issues",
language: null,
topics: [],
openIssues: 0,
dependencies: [],
mostRecentPrOpenedAt: "2021-01-01T00:00:00Z",
oldestOpenPrOpenedAt: "2022-02-02T00:00:00Z",
mostRecentIssueOpenedAt: "2023-03-03T00:00:00Z",
oldestOpenIssueOpenedAt: "2024-04-04T00:00:00Z",
},
];

const persistedData = {
repos: storedRepos,
repo1: {
owner: "dxw",
main: {
name: "repo1",
description: "description1",
updatedAt: "2021-01-01T00:00:00Z",
htmlUrl: "http://url.com/repo1",
apiUrl: "http://api.com/repo1",
pullsUrl: "http://api.com/repo1/pulls",
issuesUrl: "http://api.com/repo1/issues",
language: null,
topics: [],
openIssues: 0,
dependencies: [],
mostRecentPrOpenedAt: "2021-01-01T00:00:00Z",
oldestOpenPrOpenedAt: "2022-02-02T00:00:00Z",
mostRecentIssueOpenedAt: "2023-03-03T00:00:00Z",
oldestOpenIssueOpenedAt: "2024-04-04T00:00:00Z",
},
},
};

const expected = [
Expand Down Expand Up @@ -59,45 +58,47 @@ describe("mapRepoFromStorageToUi", () => {
});

it("converts the language string to a Tailwind colour", () => {
const storedRepos = [
{
name: "repo1",
description: "description1",
updatedAt: "2021-01-01T00:00:00Z",
htmlUrl: "http://url.com/repo1",
apiUrl: "http://api.com/repo1",
pullsUrl: "http://api.com/repo1/pulls",
issuesUrl: "http://api.com/repo1/issues",
language: "Ruby",
topics: [],
openIssues: 0,
dependencies: [],
mostRecentPrOpenedAt: "2021-01-01T00:00:00Z",
oldestOpenPrOpenedAt: "2022-02-02T00:00:00Z",
mostRecentIssueOpenedAt: "2023-03-03T00:00:00Z",
oldestOpenIssueOpenedAt: "2024-04-04T00:00:00Z",
const persistedData = {
repo1: {
owner: "dxw",
main: {
name: "repo1",
description: "description1",
updatedAt: "2021-01-01T00:00:00Z",
htmlUrl: "http://url.com/repo1",
apiUrl: "http://api.com/repo1",
pullsUrl: "http://api.com/repo1/pulls",
issuesUrl: "http://api.com/repo1/issues",
language: "Ruby",
topics: [],
openIssues: 0,
dependencies: [],
mostRecentPrOpenedAt: "2021-01-01T00:00:00Z",
oldestOpenPrOpenedAt: "2022-02-02T00:00:00Z",
mostRecentIssueOpenedAt: "2023-03-03T00:00:00Z",
oldestOpenIssueOpenedAt: "2024-04-04T00:00:00Z",
},
},
{
name: "repo2",
description: "description2",
updatedAt: "2021-01-01T00:00:00Z",
htmlUrl: "http://url.com/repo2",
apiUrl: "http://api.com/repo2",
pullsUrl: "http://api.com/repo2/pulls",
issuesUrl: "http://api.com/repo2/issues",
language: "TypeScript",
topics: [],
openIssues: 0,
dependencies: [],
mostRecentPrOpenedAt: "2021-01-01T00:00:00Z",
oldestOpenPrOpenedAt: "2022-02-02T00:00:00Z",
mostRecentIssueOpenedAt: "2023-03-03T00:00:00Z",
oldestOpenIssueOpenedAt: "2024-04-04T00:00:00Z",
repo2: {
owner: "dxw",
main: {
name: "repo2",
description: "description2",
updatedAt: "2021-01-01T00:00:00Z",
htmlUrl: "http://url.com/repo2",
apiUrl: "http://api.com/repo2",
pullsUrl: "http://api.com/repo2/pulls",
issuesUrl: "http://api.com/repo2/issues",
language: "TypeScript",
topics: [],
openIssues: 0,
dependencies: [],
mostRecentPrOpenedAt: "2021-01-01T00:00:00Z",
oldestOpenPrOpenedAt: "2022-02-02T00:00:00Z",
mostRecentIssueOpenedAt: "2023-03-03T00:00:00Z",
oldestOpenIssueOpenedAt: "2024-04-04T00:00:00Z",
},
},
];

const persistedData = {
repos: storedRepos,
};

const expected = [
Expand Down Expand Up @@ -153,49 +154,55 @@ describe("mapRepoFromStorageToUi", () => {
});

it("returns a count of the number of repos", () => {
const storedRepos = [
{
name: "repo1",
description: "description1",
updatedAt: "2021-01-01T00:00:00Z",
htmlUrl: "http://url.com/repo1",
apiUrl: "http://api.com/repo1",
pullsUrl: "http://api.com/repo1/pulls",
issuesUrl: "http://api.com/repo1/issues",
language: null,
topics: [],
openIssues: 0,
dependencies: [],
const persistedData = {
repo1: {
owner: "dxw",
main: {
name: "repo1",
description: "description1",
updatedAt: "2021-01-01T00:00:00Z",
htmlUrl: "http://url.com/repo1",
apiUrl: "http://api.com/repo1",
pullsUrl: "http://api.com/repo1/pulls",
issuesUrl: "http://api.com/repo1/issues",
language: null,
topics: [],
openIssues: 0,
dependencies: [],
},
},
{
name: "repo2",
description: "description2",
updatedAt: "2021-01-01T00:00:00Z",
htmlUrl: "http://url.com/repo2",
apiUrl: "http://api.com/repo2",
pullsUrl: "http://api.com/repo2/pulls",
issuesUrl: "http://api.com/repo2/issues",
language: null,
topics: [],
openIssues: 0,
dependencies: [],
repo2: {
owner: "dxw",
main: {
name: "repo2",
description: "description2",
updatedAt: "2021-01-01T00:00:00Z",
htmlUrl: "http://url.com/repo2",
apiUrl: "http://api.com/repo2",
pullsUrl: "http://api.com/repo2/pulls",
issuesUrl: "http://api.com/repo2/issues",
language: null,
topics: [],
openIssues: 0,
dependencies: [],
},
},
{
name: "repo3",
description: "description3",
updatedAt: "2021-01-01T00:00:00Z",
htmlUrl: "http://url.com/repo3",
apiUrl: "http://api.com/repo3",
pullsUrl: "http://api.com/repo3/pulls",
issuesUrl: "http://api.com/repo3/issues",
language: null,
topics: [],
openIssues: 0,
dependencies: [],
repo3: {
owner: "dxw",
main: {
name: "repo3",
description: "description3",
updatedAt: "2021-01-01T00:00:00Z",
htmlUrl: "http://url.com/repo3",
apiUrl: "http://api.com/repo3",
pullsUrl: "http://api.com/repo3/pulls",
issuesUrl: "http://api.com/repo3/issues",
language: null,
topics: [],
openIssues: 0,
dependencies: [],
},
},
];
const persistedData = {
repos: storedRepos,
};

expect.deepEqual(mapRepoFromStorageToUi(persistedData).totalRepos, 3);
Expand Down Expand Up @@ -353,6 +360,7 @@ describe("mapRepoFromStorageToUi", () => {

const repoToSave = {
name: "security-alert-notifier",
owner: "dxw",
description:
"Icinga plugin to fetch security vulnerabilities for a GitHub organization.",
htmlUrl: "https://github.com/dxw/security-alert-notifier",
Expand Down

0 comments on commit d46db7a

Please sign in to comment.