Implement RFID tag dump PWA with REST API, auth, and CI (#1)

Add Next.js app with SQLite/Drizzle storage for sites and LF/HF tag
dumps, multi-user Auth.js (credentials + optional OIDC), personal API
tokens in Settings, versioned /api/v1 for UI and future CLI use,
MCT/Proxmark/JSON import-export, PWA offline shell, Vitest tests, and
GitHub Actions CI.

Co-authored-by: Cursor Agent <[email protected]>
This commit is contained in:
Nick Trochalakis
2026-08-23 15:24:12 -07:00
committed by GitHub
co-authored by Cursor Agent
parent 5029945cc2
commit 8500d2f673
65 changed files with 13689 additions and 1 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 413 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

+47
View File
@@ -0,0 +1,47 @@
/* Simple offline cache for recently viewed pages and static assets */
const CACHE = "rfid-db-v1";
const PRECACHE = ["/", "/manifest.webmanifest", "/icons/icon-192.png", "/icons/icon-512.png"];
self.addEventListener("install", (event) => {
event.waitUntil(
caches.open(CACHE).then((cache) => cache.addAll(PRECACHE)).then(() => self.skipWaiting())
);
});
self.addEventListener("activate", (event) => {
event.waitUntil(
caches.keys().then((keys) =>
Promise.all(keys.filter((k) => k !== CACHE).map((k) => caches.delete(k)))
).then(() => self.clients.claim())
);
});
self.addEventListener("fetch", (event) => {
const req = event.request;
if (req.method !== "GET") return;
const url = new URL(req.url);
// Network-first for API
if (url.pathname.startsWith("/api/")) {
event.respondWith(
fetch(req).catch(() => caches.match(req).then((r) => r || Response.error()))
);
return;
}
// Cache-first for same-origin navigations and static
event.respondWith(
caches.match(req).then((cached) => {
const fetched = fetch(req)
.then((res) => {
if (res.ok && url.origin === self.location.origin) {
const clone = res.clone();
caches.open(CACHE).then((cache) => cache.put(req, clone));
}
return res;
})
.catch(() => cached);
return cached || fetched;
})
);
});