chore: standardize security and quality foundations
Magent CI/CD / verify (push) Failing after 9m34s
Magent CI/CD / deploy-beta (push) Skipped

This commit is contained in:
2026-09-17 20:03:47 +12:00
parent 5639dbcb83
commit f852e7c941
127 changed files with 17928 additions and 10741 deletions
+56 -56
View File
@@ -1,95 +1,95 @@
'use client'
"use client";
import PageHeading from '../ui/PageHeading'
import PageHeading from "../ui/PageHeading";
import { useEffect, useMemo, useState } from 'react'
import { useRouter } from 'next/navigation'
import { authFetch, clearToken, getApiBase, getToken } from '../lib/auth'
import { useEffect, useMemo, useState } from "react";
import { useRouter } from "next/navigation";
import { authFetch, clearToken, getApiBase, getToken } from "../lib/auth";
type SiteInfo = {
changelog?: string
}
changelog?: string;
};
type ChangelogGroup = {
date: string
entries: string[]
}
date: string;
entries: string[];
};
const DATE_PATTERN = /^\d{4}-\d{2}-\d{2}$/
const DATE_PATTERN = /^\d{4}-\d{2}-\d{2}$/;
const parseChangelog = (raw: string): ChangelogGroup[] => {
const groups: ChangelogGroup[] = []
for (const rawLine of raw.split('\n')) {
const line = rawLine.trim()
if (!line) continue
const [candidateDate, ...messageParts] = line.split('|')
const groups: ChangelogGroup[] = [];
for (const rawLine of raw.split("\n")) {
const line = rawLine.trim();
if (!line) continue;
const [candidateDate, ...messageParts] = line.split("|");
if (DATE_PATTERN.test(candidateDate) && messageParts.length > 0) {
const message = messageParts.join('|').trim()
if (!message) continue
const currentGroup = groups[groups.length - 1]
const message = messageParts.join("|").trim();
if (!message) continue;
const currentGroup = groups[groups.length - 1];
if (currentGroup?.date === candidateDate) {
currentGroup.entries.push(message)
currentGroup.entries.push(message);
} else {
groups.push({ date: candidateDate, entries: [message] })
groups.push({ date: candidateDate, entries: [message] });
}
continue
continue;
}
if (groups.length === 0) {
groups.push({ date: 'Updates', entries: [line] })
groups.push({ date: "Updates", entries: [line] });
} else {
groups[groups.length - 1].entries.push(line)
groups[groups.length - 1].entries.push(line);
}
}
return groups
}
return groups;
};
export default function ChangelogPage() {
const router = useRouter()
const [groups, setGroups] = useState<ChangelogGroup[]>([])
const [loading, setLoading] = useState(true)
const router = useRouter();
const [groups, setGroups] = useState<ChangelogGroup[]>([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
const token = getToken()
const token = getToken();
if (!token) {
router.push('/login')
return
router.push("/login");
return;
}
let active = true
let active = true;
const load = async () => {
try {
const baseUrl = getApiBase()
const response = await authFetch(`${baseUrl}/site/info`)
const baseUrl = getApiBase();
const response = await authFetch(`${baseUrl}/site/info`);
if (!response.ok) {
if (response.status === 401) {
clearToken()
router.push('/login')
return
clearToken();
router.push("/login");
return;
}
throw new Error('Failed to load changelog')
throw new Error("Failed to load changelog");
}
const data: SiteInfo = await response.json()
if (!active) return
setGroups(parseChangelog(data?.changelog ?? ''))
const data: SiteInfo = await response.json();
if (!active) return;
setGroups(parseChangelog(data?.changelog ?? ""));
} catch (err) {
console.error(err)
if (!active) return
setGroups([])
console.error(err);
if (!active) return;
setGroups([]);
} finally {
if (active) setLoading(false)
if (active) setLoading(false);
}
}
void load()
};
void load();
return () => {
active = false
}
}, [router])
active = false;
};
}, [router]);
const content = useMemo(() => {
if (loading) {
return <div className="loading-text">Loading changelog...</div>
return <div className="loading-text">Loading changelog...</div>;
}
if (groups.length === 0) {
return <div className="meta">No updates posted yet.</div>
return <div className="meta">No updates posted yet.</div>;
}
return (
<div className="changelog-groups">
@@ -104,13 +104,13 @@ export default function ChangelogPage() {
</section>
))}
</div>
)
}, [groups, loading])
);
}, [groups, loading]);
return (
<main className="card changelog-page">
<PageHeading title="Changelog" description="Whats new and improved in Magent." />
{content}
</main>
)
);
}