mirror of
https://github.com/trafficlunar/tomodachi-share.git
synced 2026-09-28 03:51:44 +00:00
Compare commits
No commits in common. "041689392bd1c1001d671627fbd2551269817c6a" and "c5e0b08b7ed7d0ee759f7c9ba51ba4b29f1bdadb" have entirely different histories.
041689392b
...
c5e0b08b7e
9 changed files with 453 additions and 982 deletions
|
|
@ -2,7 +2,7 @@
|
||||||
"name": "@tomodachi-share/backend",
|
"name": "@tomodachi-share/backend",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"packageManager": "pnpm@11.24.0",
|
"packageManager": "pnpm@11.18.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev",
|
"dev": "next dev",
|
||||||
"build": "next build",
|
"build": "next build",
|
||||||
|
|
@ -17,30 +17,30 @@
|
||||||
"@tomodachi-share/shared": "workspace:*",
|
"@tomodachi-share/shared": "workspace:*",
|
||||||
"bit-buffer": "^0.3.0",
|
"bit-buffer": "^0.3.0",
|
||||||
"charinfo-ex": "^0.0.5",
|
"charinfo-ex": "^0.0.5",
|
||||||
"dayjs": "^1.11.23",
|
"dayjs": "^1.11.21",
|
||||||
"downshift": "^9.4.0",
|
"downshift": "^9.4.0",
|
||||||
"file-type": "^22.0.2",
|
"file-type": "^22.0.1",
|
||||||
"next": "16.3.3",
|
"next": "16.2.12",
|
||||||
"next-auth": "5.0.0-beta.32",
|
"next-auth": "5.0.0-beta.32",
|
||||||
"qrcode-generator": "^2.0.4",
|
"qrcode-generator": "^2.0.4",
|
||||||
"react": "^19.2.8",
|
"react": "^19.2.8",
|
||||||
"react-dom": "^19.2.8",
|
"react-dom": "^19.2.8",
|
||||||
"redis": "^6.2.1",
|
"redis": "^6.2.0",
|
||||||
"satori": "^0.33.4",
|
"satori": "^0.29.0",
|
||||||
"sharp": "^0.34.5",
|
"sharp": "^0.34.5",
|
||||||
"sjcl-with-all": "1.0.8",
|
"sjcl-with-all": "1.0.8",
|
||||||
"zod": "^4.5.4"
|
"zod": "^4.4.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/eslintrc": "^3.3.6",
|
"@eslint/eslintrc": "^3.3.6",
|
||||||
"@iconify/react": "^6.0.2",
|
"@iconify/react": "^6.0.2",
|
||||||
"@tailwindcss/postcss": "^4.3.3",
|
"@tailwindcss/postcss": "^4.3.3",
|
||||||
"@types/node": "^26.4.0",
|
"@types/node": "^26.1.2",
|
||||||
"@types/react": "^19.2.18",
|
"@types/react": "^19.2.18",
|
||||||
"@types/react-dom": "^19.2.5",
|
"@types/react-dom": "^19.2.4",
|
||||||
"@types/sjcl": "^1.0.34",
|
"@types/sjcl": "^1.0.34",
|
||||||
"eslint": "^10.9.1",
|
"eslint": "^10.8.0",
|
||||||
"eslint-config-next": "16.3.3",
|
"eslint-config-next": "16.2.12",
|
||||||
"prisma": "^6.19.3",
|
"prisma": "^6.19.3",
|
||||||
"schema-dts": "^2.0.0",
|
"schema-dts": "^2.0.0",
|
||||||
"tailwindcss": "^4.3.3",
|
"tailwindcss": "^4.3.3",
|
||||||
|
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
import { prisma } from "@/lib/prisma";
|
|
||||||
import { CHUNK_SIZE } from "../sitemap";
|
|
||||||
import { NextResponse } from "next/server";
|
|
||||||
|
|
||||||
export const revalidate = 43200; // update every 12 hours
|
|
||||||
|
|
||||||
export async function GET() {
|
|
||||||
const apiUrl = process.env.NEXT_PUBLIC_BASE_URL!;
|
|
||||||
|
|
||||||
const total = await prisma.mii.count({
|
|
||||||
where: { in_queue: false, quarantined: false },
|
|
||||||
});
|
|
||||||
const miiChunks = Math.ceil(total / CHUNK_SIZE);
|
|
||||||
const totalSitemaps = miiChunks + 1; // +1 for the static-routes sitemap
|
|
||||||
|
|
||||||
const sitemapEntries = Array.from({ length: totalSitemaps }, (_, i) => `<sitemap><loc>${apiUrl}/sitemap/${i}.xml</loc></sitemap>`).join("");
|
|
||||||
|
|
||||||
const xml = `<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
|
||||||
${sitemapEntries}
|
|
||||||
</sitemapindex>`;
|
|
||||||
|
|
||||||
return new NextResponse(xml, {
|
|
||||||
headers: { "Content-Type": "application/xml" },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
@ -4,27 +4,51 @@ import type { MetadataRoute } from "next";
|
||||||
type SitemapRoute = MetadataRoute.Sitemap[0];
|
type SitemapRoute = MetadataRoute.Sitemap[0];
|
||||||
|
|
||||||
export const revalidate = 43200; // update every 12 hours
|
export const revalidate = 43200; // update every 12 hours
|
||||||
export const CHUNK_SIZE = 45000; // stay under 50,000 limit
|
|
||||||
|
|
||||||
export async function generateSitemaps() {
|
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
|
||||||
const total = await prisma.mii.count({
|
const baseUrl = process.env.NEXT_PUBLIC_FRONTEND_URL!;
|
||||||
|
const apiUrl = process.env.NEXT_PUBLIC_BASE_URL!;
|
||||||
|
|
||||||
|
const miis = await prisma.mii.findMany({
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
createdAt: true,
|
||||||
|
},
|
||||||
where: {
|
where: {
|
||||||
in_queue: false,
|
in_queue: false,
|
||||||
quarantined: false,
|
quarantined: false,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const miiChunks = Math.ceil(total / CHUNK_SIZE);
|
|
||||||
|
|
||||||
// id 0 = static routes, ids 1..miiChunks = mii chunks
|
// const users = await prisma.user.findMany({
|
||||||
return Array.from({ length: miiChunks + 1 }, (_, id) => ({ id }));
|
// select: {
|
||||||
}
|
// id: true,
|
||||||
|
// updatedAt: true,
|
||||||
|
// },
|
||||||
|
// });
|
||||||
|
|
||||||
export default async function sitemap(props: { id: Promise<string> }): Promise<MetadataRoute.Sitemap> {
|
const dynamicRoutes: MetadataRoute.Sitemap = [
|
||||||
const baseUrl = process.env.NEXT_PUBLIC_FRONTEND_URL!;
|
...miis.map(
|
||||||
const apiUrl = process.env.NEXT_PUBLIC_BASE_URL!;
|
(mii) =>
|
||||||
|
({
|
||||||
|
url: `${baseUrl}/mii/${mii.id}`,
|
||||||
|
lastModified: mii.createdAt,
|
||||||
|
changeFrequency: "weekly",
|
||||||
|
priority: 0.7,
|
||||||
|
images: [`${apiUrl}/mii/${mii.id}/image?type=metadata`],
|
||||||
|
}) as SitemapRoute,
|
||||||
|
),
|
||||||
|
// ...users.map(
|
||||||
|
// (user) =>
|
||||||
|
// ({
|
||||||
|
// url: `${baseUrl}/profile/${user.id}`,
|
||||||
|
// lastModified: user.updatedAt,
|
||||||
|
// changeFrequency: "weekly",
|
||||||
|
// priority: 0.2,
|
||||||
|
// }) as SitemapRoute,
|
||||||
|
// ),
|
||||||
|
];
|
||||||
|
|
||||||
// id 0: static routes only
|
|
||||||
if ((await props.id) === "0") {
|
|
||||||
const lastModified = new Date();
|
const lastModified = new Date();
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
|
@ -52,34 +76,6 @@ export default async function sitemap(props: { id: Promise<string> }): Promise<M
|
||||||
changeFrequency: "yearly",
|
changeFrequency: "yearly",
|
||||||
priority: 0.4,
|
priority: 0.4,
|
||||||
},
|
},
|
||||||
|
...dynamicRoutes,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
// id 1+: paginated mii chunks
|
|
||||||
const chunkIndex = Number(await props.id) - 1;
|
|
||||||
|
|
||||||
const miis = await prisma.mii.findMany({
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
createdAt: true,
|
|
||||||
},
|
|
||||||
where: {
|
|
||||||
in_queue: false,
|
|
||||||
quarantined: false,
|
|
||||||
},
|
|
||||||
orderBy: { id: "asc" },
|
|
||||||
skip: chunkIndex * CHUNK_SIZE,
|
|
||||||
take: CHUNK_SIZE,
|
|
||||||
});
|
|
||||||
|
|
||||||
return miis.map(
|
|
||||||
(mii) =>
|
|
||||||
({
|
|
||||||
url: `${baseUrl}/mii/${mii.id}`,
|
|
||||||
lastModified: mii.createdAt,
|
|
||||||
changeFrequency: "weekly",
|
|
||||||
priority: 0.7,
|
|
||||||
images: [`${apiUrl}/mii/${mii.id}/image?type=metadata`],
|
|
||||||
}) as SitemapRoute,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -17,37 +17,37 @@
|
||||||
"@tailwindcss/vite": "^4.3.3",
|
"@tailwindcss/vite": "^4.3.3",
|
||||||
"@tomodachi-share/shared": "workspace:*",
|
"@tomodachi-share/shared": "workspace:*",
|
||||||
"@types/react": "^19.2.18",
|
"@types/react": "^19.2.18",
|
||||||
"@types/react-dom": "^19.2.5",
|
"@types/react-dom": "^19.2.4",
|
||||||
"canvas-confetti": "^1.9.4",
|
"canvas-confetti": "^1.9.4",
|
||||||
"dayjs": "^1.11.23",
|
"dayjs": "^1.11.21",
|
||||||
"downshift": "^9.4.0",
|
"downshift": "^9.4.0",
|
||||||
"embla-carousel-react": "^8.6.0",
|
"embla-carousel-react": "^8.6.0",
|
||||||
"jsqr": "^1.4.0",
|
"jsqr": "^1.4.0",
|
||||||
"nanostores": "^1.5.2",
|
"nanostores": "^1.4.2",
|
||||||
"qrcode-generator": "^2.0.4",
|
"qrcode-generator": "^2.0.4",
|
||||||
"react": "^19.2.8",
|
"react": "^19.2.8",
|
||||||
"react-dom": "^19.2.8",
|
"react-dom": "^19.2.8",
|
||||||
"react-dropzone": "^20.1.1",
|
"react-dropzone": "^19.1.1",
|
||||||
"react-image-crop": "^11.1.2",
|
"react-image-crop": "^11.1.2",
|
||||||
"react-router": "^8.3.1",
|
"react-router": "^8.3.0",
|
||||||
"tailwindcss": "^4.3.3",
|
"tailwindcss": "^4.3.3",
|
||||||
"vite-plugin-node-polyfills": "^0.28.0",
|
"vite-plugin-node-polyfills": "^0.26.0",
|
||||||
"zod": "^4.5.4"
|
"zod": "^4.4.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^10.0.1",
|
"@eslint/js": "^10.0.1",
|
||||||
"@iconify/react": "^6.0.2",
|
"@iconify/react": "^6.0.2",
|
||||||
"@types/canvas-confetti": "^1.9.0",
|
"@types/canvas-confetti": "^1.9.0",
|
||||||
"@types/node": "^26.4.0",
|
"@types/node": "^26.1.2",
|
||||||
"@types/react": "^19.2.18",
|
"@types/react": "^19.2.14",
|
||||||
"@types/react-dom": "^19.2.5",
|
"@types/react-dom": "^19.2.3",
|
||||||
"@vitejs/plugin-react": "^6.1.1",
|
"@vitejs/plugin-react": "^6.0.5",
|
||||||
"eslint": "^10.9.1",
|
"eslint": "^10.8.0",
|
||||||
"eslint-plugin-react-hooks": "^7.1.1",
|
"eslint-plugin-react-hooks": "^7.1.1",
|
||||||
"eslint-plugin-react-refresh": "^0.5.5",
|
"eslint-plugin-react-refresh": "^0.5.3",
|
||||||
"globals": "^17.11.0",
|
"globals": "^17.8.0",
|
||||||
"typescript": "~7.0.2",
|
"typescript": "~7.0.2",
|
||||||
"typescript-eslint": "^8.68.0",
|
"typescript-eslint": "^8.65.0",
|
||||||
"vite": "^8.2.2"
|
"vite": "^8.2.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,4 +10,4 @@ Disallow: /report/mii/*
|
||||||
Disallow: /report/user/*
|
Disallow: /report/user/*
|
||||||
Disallow: /admin
|
Disallow: /admin
|
||||||
|
|
||||||
Sitemap: https://api.tomodachishare.com/sitemap-index.xml
|
Sitemap: https://api.tomodachishare.com/sitemap.xml
|
||||||
|
|
|
||||||
|
|
@ -9,5 +9,5 @@
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
"author": "",
|
"author": "",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"packageManager": "pnpm@11.24.0"
|
"packageManager": "pnpm@11.18.0"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
1221
pnpm-lock.yaml
generated
1221
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load diff
|
|
@ -17,4 +17,3 @@ minimumReleaseAgeExclude:
|
||||||
- '@redis/search@6.2.0'
|
- '@redis/search@6.2.0'
|
||||||
- '@redis/time-series@6.2.0'
|
- '@redis/time-series@6.2.0'
|
||||||
- redis@6.2.0
|
- redis@6.2.0
|
||||||
- zod@4.5.4
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
"fzstd": "^0.1.1",
|
"fzstd": "^0.1.1",
|
||||||
"sharp": "^0.34.5",
|
"sharp": "^0.34.5",
|
||||||
"sjcl-with-all": "1.0.8",
|
"sjcl-with-all": "1.0.8",
|
||||||
"zod": "^4.5.4"
|
"zod": "^4.4.3"
|
||||||
},
|
},
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./src/index.ts",
|
".": "./src/index.ts",
|
||||||
|
|
@ -17,8 +17,7 @@
|
||||||
},
|
},
|
||||||
"types": "./src/index.ts",
|
"types": "./src/index.ts",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^26.4.0",
|
"@types/node": "^26.1.2",
|
||||||
"@types/sjcl": "^1.0.34",
|
"@types/sjcl": "^1.0.34"
|
||||||
"vite-plugin-node-polyfills": "^0.28.0"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue