From d8be1c0a6999492052f8db22b06255417fc862e2 Mon Sep 17 00:00:00 2001 From: Marios Antonoudiou Date: Fri, 6 Mar 2026 19:11:41 +0200 Subject: [PATCH] Feed the database --- .../database/migrations/0001_round_husk.sql | 16 ++ .../migrations/meta/0001_snapshot.json | 204 ++++++++++++++++++ server/database/migrations/meta/_journal.json | 7 + server/database/schema.ts | 6 +- server/plugins/feed.ts | 116 ++++++++++ 5 files changed, 346 insertions(+), 3 deletions(-) create mode 100644 server/database/migrations/0001_round_husk.sql create mode 100644 server/database/migrations/meta/0001_snapshot.json create mode 100644 server/plugins/feed.ts diff --git a/server/database/migrations/0001_round_husk.sql b/server/database/migrations/0001_round_husk.sql new file mode 100644 index 0000000..104e60b --- /dev/null +++ b/server/database/migrations/0001_round_husk.sql @@ -0,0 +1,16 @@ +PRAGMA foreign_keys=OFF;--> statement-breakpoint +CREATE TABLE `__new_users` ( + `id` numeric PRIMARY KEY NOT NULL, + `name` text NOT NULL, + `avatar` text, + `city` text, + `country` text, + `sex` text, + `weight` integer, + `created_at` integer +); +--> statement-breakpoint +INSERT INTO `__new_users`("id", "name", "avatar", "city", "country", "sex", "weight", "created_at") SELECT "id", "name", "avatar", "city", "country", "sex", "weight", "created_at" FROM `users`;--> statement-breakpoint +DROP TABLE `users`;--> statement-breakpoint +ALTER TABLE `__new_users` RENAME TO `users`;--> statement-breakpoint +PRAGMA foreign_keys=ON; \ No newline at end of file diff --git a/server/database/migrations/meta/0001_snapshot.json b/server/database/migrations/meta/0001_snapshot.json new file mode 100644 index 0000000..a29aad6 --- /dev/null +++ b/server/database/migrations/meta/0001_snapshot.json @@ -0,0 +1,204 @@ +{ + "version": "6", + "dialect": "sqlite", + "id": "80d98e5a-f977-4e9c-889b-ae77c99d8238", + "prevId": "d9537942-cba2-4af4-8396-533366512937", + "tables": { + "preferences": { + "name": "preferences", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "user_id": { + "name": "user_id", + "type": "numeric", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "data": { + "name": "data", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "preferences_user_id_unique": { + "name": "preferences_user_id_unique", + "columns": [ + "user_id" + ], + "isUnique": true + } + }, + "foreignKeys": { + "preferences_user_id_users_id_fk": { + "name": "preferences_user_id_users_id_fk", + "tableFrom": "preferences", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "tokens": { + "name": "tokens", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "user_id": { + "name": "user_id", + "type": "numeric", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "refresh_token": { + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "expires_at": { + "name": "expires_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "tokens_user_id_unique": { + "name": "tokens_user_id_unique", + "columns": [ + "user_id" + ], + "isUnique": true + } + }, + "foreignKeys": { + "tokens_user_id_users_id_fk": { + "name": "tokens_user_id_users_id_fk", + "tableFrom": "tokens", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "users": { + "name": "users", + "columns": { + "id": { + "name": "id", + "type": "numeric", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "avatar": { + "name": "avatar", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "city": { + "name": "city", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "country": { + "name": "country", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "sex": { + "name": "sex", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "weight": { + "name": "weight", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + } + }, + "views": {}, + "enums": {}, + "_meta": { + "schemas": {}, + "tables": {}, + "columns": {} + }, + "internal": { + "indexes": {} + } +} \ No newline at end of file diff --git a/server/database/migrations/meta/_journal.json b/server/database/migrations/meta/_journal.json index 0c0a47d..a7e3775 100644 --- a/server/database/migrations/meta/_journal.json +++ b/server/database/migrations/meta/_journal.json @@ -8,6 +8,13 @@ "when": 1772727834477, "tag": "0000_living_oracle", "breakpoints": true + }, + { + "idx": 1, + "version": "6", + "when": 1772816922744, + "tag": "0001_round_husk", + "breakpoints": true } ] } \ No newline at end of file diff --git a/server/database/schema.ts b/server/database/schema.ts index 5d933c5..4003b58 100644 --- a/server/database/schema.ts +++ b/server/database/schema.ts @@ -9,9 +9,9 @@ export const users = sqliteTable("users", { country: text("country"), sex: text("sex"), weight: integer("weight"), - createdAt: integer("created_at", { mode: "timestamp" }) - .notNull() - .$defaultFn(() => new Date()), + createdAt: integer("created_at", { mode: "timestamp" }).$defaultFn( + () => new Date(), + ), }); export const preferences = sqliteTable("preferences", { diff --git a/server/plugins/feed.ts b/server/plugins/feed.ts new file mode 100644 index 0000000..c8584b8 --- /dev/null +++ b/server/plugins/feed.ts @@ -0,0 +1,116 @@ +import { drizzle } from "drizzle-orm/bun-sqlite"; +import { existsSync } from "node:fs"; +import { readFileSync } from "node:fs"; +import * as schema from "../database/schema"; + +interface FeedItem { + user: { + id: number; + name: string; + avatar: string | null; + city: string | null; + country: string | null; + sex: string | null; + weight: number | null; + created_at: string; + }; + token: { + id: number; + user_id: number; + refresh_token: string; + access_token: string; + expires_at: string; + }; + preferences: { + tone: string[]; + units: "Imperial" | "Metric"; + enabled: boolean; + language: string; + }; +} + +export default defineNitroPlugin(async () => { + const config = useRuntimeConfig(); + const feedPath = "tmp/feed.json"; + + if (!existsSync(feedPath)) { + return; + } + + console.log("Processing feed.json..."); + + const db = drizzle(config.databaseUrl, { schema }); + const feed: FeedItem[] = JSON.parse(readFileSync(feedPath, "utf-8")); + + for (const item of feed) { + const userId = String(item.user.id); + + await db + .insert(schema.users) + .values({ + id: userId, + name: item.user.name, + avatar: item.user.avatar, + city: item.user.city, + country: item.user.country, + sex: item.user.sex, + weight: item.user.weight, + createdAt: new Date(item.user.created_at), + }) + .onConflictDoUpdate({ + target: schema.users.id, + set: { + name: item.user.name, + avatar: item.user.avatar, + city: item.user.city, + country: item.user.country, + sex: item.user.sex, + weight: item.user.weight, + }, + }); + + await db + .insert(schema.tokens) + .values({ + userId: userId, + refreshToken: item.token.refresh_token, + accessToken: item.token.access_token, + expiresAt: new Date(item.token.expires_at), + }) + .onConflictDoUpdate({ + target: schema.tokens.userId, + set: { + refreshToken: item.token.refresh_token, + accessToken: item.token.access_token, + expiresAt: new Date(item.token.expires_at), + }, + }); + + await db + .insert(schema.preferences) + .values({ + userId: userId, + data: { + enabled: item.preferences.enabled, + language: item.preferences.language, + units: item.preferences.units, + tone: item.preferences.tone, + highlights: [], + }, + }) + .onConflictDoUpdate({ + target: schema.preferences.userId, + set: { + data: { + enabled: item.preferences.enabled, + language: item.preferences.language, + units: item.preferences.units, + tone: item.preferences.tone, + highlights: [], + }, + }, + }); + } + + console.log(`Processed ${feed.length} feed items`); +});