feat: add recent data in top page

This commit is contained in:
Keisuke Hirata 2024-08-25 10:13:53 +09:00
parent 25f5675612
commit 64d3e51311
4 changed files with 471 additions and 358 deletions

721
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -35,6 +35,7 @@
"type": "module",
"dependencies": {
"dotenv": "^16.4.5",
"mdsvex": "^0.12.3",
"pg": "^8.12.0",
"sass": "^1.77.8"
}

View File

@ -1,7 +1,7 @@
// initialize
import PG from '$lib/server/database';
import fs from 'fs';
import { compile } from 'mdsvex';
export default async function init() {
@ -13,9 +13,12 @@ export default async function init() {
{ name: 'seq', type: 'serial', constraint: 'primary key' },
{ name: 'id', type: 'text', constraint: 'not null' },
{ name: 'title', type: 'text', constraint: 'not null' },
{ name: 'category', type: 'text', constraint: 'not null' },
{ name: 'released_at', type: 'timestamp', constraint: 'not null' },
{ name: 'updated_at', type: 'timestamp', constraint: 'not null' },
{ name: 'tags', type: 'text[]', constraint: 'not null' },
{ name: 'image', type: 'text', constraint: '' },
{ name: 'publish', type: 'text', constraint: 'not null' },
{ name: 'content', type: 'text', constraint: 'not null' },
],
},
@ -34,6 +37,7 @@ export default async function init() {
{ name: 'seq', type: 'serial', constraint: 'primary key' },
{ name: 'id', type: 'text', constraint: 'not null' },
{ name: 'title', type: 'text', constraint: 'not null' },
{ name: 'category', type: 'text', constraint: 'not null' },
{ name: 'created_at', type: 'timestamp', constraint: 'not null' },
{ name: 'updated_at', type: 'timestamp', constraint: 'not null' },
{ name: 'tags', type: 'text[]', constraint: 'not null' },
@ -58,8 +62,17 @@ export default async function init() {
{ name: 'posted_at', type: 'timestamp', constraint: 'not null' },
{ name: 'content', type: 'text', constraint: 'not null' },
],
},
{
name: 'tag',
columns: [
{ name: 'seq', type: 'serial', constraint: 'primary key' },
{ name: 'name', type: 'text', constraint: 'not null' },
{ name: 'ref_count', type: 'integer', constraint: 'not null' },
],
}
];
const db = await PG();
try {
await db.begin();
@ -79,7 +92,6 @@ export default async function init() {
await db.rollback();
}
// Check if the article are already in the database
const articleFiles: ArticleFileItem[] = [];
function scanDir(path: string) {
const files = fs.readdirSync(path);
@ -89,13 +101,51 @@ export default async function init() {
if (stat.isDirectory()) {
scanDir(dir);
} else {
// articleFiles.push({ path: `${path}/${file}`, id: file });
console.log(`${path}/${file}`);
articleFiles.push({ path: `${path}/${file}`, id: file });
}
}
}
scanDir('./articles/dist');
await db.query('update tag set ref_count = 0');
db.commit();
for (const { path, id } of articleFiles) {
const res = await db.query('select * from article where id = $1', [id]);
const md = await compile(fs.readFileSync(path, 'utf-8'));
const title = md.data.fm.title;
const category = path.split('/')[3];
const tags: string[] = md.data.fm.tags;
const released_at = new Date(md.data.fm.released_at);
const updated_at = new Date(md.data.fm.updated_at);
const image = md.data.fm.image;
const publish = md.data.fm.publish;
const content = md.code;
if (res.rowCount == 0) {
console.log(`New article: ${id}`);
await db.query(
'insert into article (id, title, category, released_at, updated_at, tags, image, publish, content) values ($1, $2, $3, $4, $5, $6, $7, $8, $9)',
[id, title, category, released_at, updated_at, tags, image, publish, content]
);
} else if (res.rows[0].updated_at < updated_at) {
console.log(`Update article: ${id}`);
await db.query(
'update article set title = $2, updated_at = $4, tags = $5, content = $6 where id = $1',
[id, title, updated_at, tags, content]
);
} else {
console.log(`Article ${id} is already up-to-date`);
}
for (const tag of tags) {
if ((await db.query('select * from tag where name = $1', [tag])).rowCount == 0) {
db.query('insert into tag (name, ref_count) values ($1, 1)', [tag]);
} else {
db.query('update tag set ref_count = ref_count + 1 where name = $1', [tag]);
}
}
}
await db.commit();
await db.release();
}
@ -110,4 +160,4 @@ export type TableSchema = {
type: string,
constraint: string,
}[],
}
}

View File

@ -4,29 +4,46 @@ import type { Content } from '$lib/article';
import PG from '$lib/server/database';
let data: {
recent: Content[],
recent: {
title: string,
image: string,
date: string,
link: string,
tags: string[]
}[],
tags: string[],
updated: string
updated: string,
} = {
recent: [
{
title: "title",
image: "image",
date: "date",
link: "link",
tags: ["tag1", "tag2"],
},
],
tags: ["hoge", "fuga", "piyo"],
recent: [],
tags: [],
updated: "",
};
export const load: PageServerLoad = async ({ params }) => {
const db = await PG();
const now = await db.query('SELECT NOW()');
await db.release();
await db.begin();
try {
const recent_articles = await db.query(
"SELECT * FROM article WHERE publish = 'public' ORDER BY updated_at DESC LIMIT 4"
);
data.recent = recent_articles.rows.map((row) => ({
title: row.title,
image: row.image,
date: row.updated_at.toISOString().slice(0, 10),
link: `/post/${row.category}/${row.id}`,
tags: row.tags,
}));
const tags = await db.query("SELECT * FROM tag ORDER BY ref_count DESC");
data.tags = tags.rows.map((row) => row.name + ":" + row.ref_count);
} catch (e) {
await db.rollback();
throw error(500, e as Error);
} finally {
await db.release();
}
data.updated = data.recent[0].date;
data.updated = now.rows[0].now;
return data;
}