Compare commits
10 Commits
41c71a9877
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 1117b4adc0 | |||
| 8de1f87435 | |||
| d82416e4a3 | |||
| 926fc0fd0b | |||
| 0370930894 | |||
| 8831857007 | |||
| 095463cafa | |||
| 742242ffb8 | |||
| 61de53c014 | |||
| cda02e35fb |
@@ -1,10 +0,0 @@
|
|||||||
.git
|
|
||||||
.gitignore
|
|
||||||
.nuxt
|
|
||||||
.output
|
|
||||||
node_modules
|
|
||||||
*.md
|
|
||||||
README*
|
|
||||||
.env
|
|
||||||
.env.*
|
|
||||||
!.env.example
|
|
||||||
28
Dockerfile
28
Dockerfile
@@ -1,28 +0,0 @@
|
|||||||
FROM oven/bun:1-alpine AS base
|
|
||||||
|
|
||||||
FROM base AS deps
|
|
||||||
WORKDIR /app
|
|
||||||
COPY package.json bun.lock* ./
|
|
||||||
RUN bun install --frozen-lockfile
|
|
||||||
|
|
||||||
FROM base AS builder
|
|
||||||
WORKDIR /app
|
|
||||||
COPY --from=deps /app/node_modules ./node_modules
|
|
||||||
COPY . .
|
|
||||||
RUN bun run build
|
|
||||||
|
|
||||||
FROM base AS runner
|
|
||||||
WORKDIR /app
|
|
||||||
ENV NODE_ENV=production
|
|
||||||
|
|
||||||
RUN addgroup --system --gid 1001 nodejs
|
|
||||||
RUN adduser --system --uid 1001 nuxt
|
|
||||||
|
|
||||||
COPY --from=builder /app/.output ./.output
|
|
||||||
COPY --from=builder /app/package.json ./
|
|
||||||
|
|
||||||
USER nuxt
|
|
||||||
|
|
||||||
EXPOSE 3000
|
|
||||||
|
|
||||||
CMD ["bun", "x", "nuxt", "start"]
|
|
||||||
18
agents.md
18
agents.md
@@ -4,25 +4,25 @@
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Development
|
# Development
|
||||||
bun run dev
|
pnpm run dev
|
||||||
|
|
||||||
# Build
|
# Build
|
||||||
bun run build
|
pnpm run build
|
||||||
|
|
||||||
# Generate static site
|
# Generate static site
|
||||||
bun run generate
|
pnpm run generate
|
||||||
|
|
||||||
# Type checking
|
# Type checking
|
||||||
bunx vue-tsc --noEmit
|
pnpm exec vue-tsc --noEmit
|
||||||
|
|
||||||
# Database
|
# Database
|
||||||
bunx drizzle-kit push
|
pnpm exec drizzle-kit push
|
||||||
bunx drizzle-kit studio
|
pnpm exec drizzle-kit studio
|
||||||
```
|
```
|
||||||
|
|
||||||
## Project Info
|
## Project Info
|
||||||
|
|
||||||
- Nuxt 4
|
- Nuxt 4
|
||||||
- Uses bun as package manager and runtime
|
- Uses pnpm as package manager and runtime
|
||||||
- Database: Drizzle ORM with Bun's sqlite
|
- Database: Drizzle ORM with sqlite
|
||||||
- UI: @nuxt/ui v3
|
- UI: @nuxt/ui v4
|
||||||
|
|||||||
@@ -50,4 +50,10 @@ export default defineNuxtConfig({
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
nitro: {
|
||||||
|
preset: "node-server",
|
||||||
|
experimental: {
|
||||||
|
tasks: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
41
package.json
41
package.json
@@ -6,40 +6,49 @@
|
|||||||
"build": "nuxt build",
|
"build": "nuxt build",
|
||||||
"dev": "nuxt dev --host=0.0.0.0",
|
"dev": "nuxt dev --host=0.0.0.0",
|
||||||
"generate": "nuxt generate",
|
"generate": "nuxt generate",
|
||||||
"postinstall": "nuxt prepare"
|
"postinstall": "nuxt prepare",
|
||||||
|
"start": "node .output/server/index.mjs"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@formkit/tempo": "^0.1.2",
|
"@formkit/tempo": "^1.0.0",
|
||||||
"@nuxt/icon": "1.15.0",
|
"@nuxt/icon": "^2.2.1",
|
||||||
"@nuxt/image": "^1.11.0",
|
"@nuxt/image": "^2.0.0",
|
||||||
"@nuxt/ui": "3.3.0",
|
"@nuxt/ui": "4.5.1",
|
||||||
"@vee-validate/nuxt": "^4.15.1",
|
"@vee-validate/nuxt": "^4.15.1",
|
||||||
"@vueuse/nuxt": "^13.6.0",
|
"@vueuse/nuxt": "^14.2.1",
|
||||||
|
"better-sqlite3": "^12.6.2",
|
||||||
"destr": "^2.0.5",
|
"destr": "^2.0.5",
|
||||||
"drizzle-orm": "^0.44.4",
|
"drizzle-orm": "^0.44.4",
|
||||||
"nuxt": "^4.0.3",
|
"nuxt": "^4.3.1",
|
||||||
"nuxt-auth-utils": "0.5.23",
|
"nuxt-auth-utils": "0.5.29",
|
||||||
"openai": "^5.12.2",
|
"openai": "^6.27.0",
|
||||||
"radash": "^12.1.1",
|
"radash": "^12.1.1",
|
||||||
"ts-pattern": "^5.8.0",
|
"ts-pattern": "^5.9.0",
|
||||||
"url": "^0.11.4",
|
"url": "^0.11.4",
|
||||||
"vue": "^3.5.18",
|
"vue": "^3.5.29",
|
||||||
"vue-router": "^4.5.1",
|
"vue-router": "^5.0.3",
|
||||||
"zod": "^4.0.16"
|
"zod": "^4.3.6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@iconify-json/heroicons": "^1.2.3",
|
"@iconify-json/heroicons": "^1.2.3",
|
||||||
"@iconify-json/lucide": "^1.2.95",
|
"@iconify-json/lucide": "^1.2.95",
|
||||||
"@types/bun": "^1.3.10",
|
"@types/better-sqlite3": "^7.6.13",
|
||||||
|
"@types/node": "^25.3.5",
|
||||||
"drizzle-kit": "^0.31.4",
|
"drizzle-kit": "^0.31.4",
|
||||||
"typescript": "^5.9.2",
|
"typescript": "^5.9.2",
|
||||||
"vue-tsc": "^3.0.5"
|
"vue-tsc": "^3.2.5"
|
||||||
},
|
},
|
||||||
"trustedDependencies": [
|
"trustedDependencies": [
|
||||||
"@parcel/watcher",
|
"@parcel/watcher",
|
||||||
|
"better-sqlite3",
|
||||||
"esbuild",
|
"esbuild",
|
||||||
"sharp",
|
"sharp",
|
||||||
"vue-demi",
|
"vue-demi",
|
||||||
"workerd"
|
"workerd"
|
||||||
]
|
],
|
||||||
|
"pnpm": {
|
||||||
|
"onlyBuiltDependencies": [
|
||||||
|
"better-sqlite3"
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
10514
pnpm-lock.yaml
generated
Normal file
10514
pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -24,5 +24,5 @@ CREATE TABLE `users` (
|
|||||||
`country` text,
|
`country` text,
|
||||||
`sex` text,
|
`sex` text,
|
||||||
`weight` integer,
|
`weight` integer,
|
||||||
`created_at` integer NOT NULL
|
`created_at` integer
|
||||||
);
|
);
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
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;
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"version": "6",
|
"version": "6",
|
||||||
"dialect": "sqlite",
|
"dialect": "sqlite",
|
||||||
"id": "d9537942-cba2-4af4-8396-533366512937",
|
"id": "347ea848-a216-4fff-910a-90ba2f9aa91c",
|
||||||
"prevId": "00000000-0000-0000-0000-000000000000",
|
"prevId": "00000000-0000-0000-0000-000000000000",
|
||||||
"tables": {
|
"tables": {
|
||||||
"preferences": {
|
"preferences": {
|
||||||
@@ -180,7 +180,7 @@
|
|||||||
"name": "created_at",
|
"name": "created_at",
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"primaryKey": false,
|
"primaryKey": false,
|
||||||
"notNull": true,
|
"notNull": false,
|
||||||
"autoincrement": false
|
"autoincrement": false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,204 +0,0 @@
|
|||||||
{
|
|
||||||
"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": {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -5,15 +5,8 @@
|
|||||||
{
|
{
|
||||||
"idx": 0,
|
"idx": 0,
|
||||||
"version": "6",
|
"version": "6",
|
||||||
"when": 1772727834477,
|
"when": 1772879556762,
|
||||||
"tag": "0000_living_oracle",
|
"tag": "0000_groovy_rachel_grey",
|
||||||
"breakpoints": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"idx": 1,
|
|
||||||
"version": "6",
|
|
||||||
"when": 1772816922744,
|
|
||||||
"tag": "0001_round_husk",
|
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,116 +0,0 @@
|
|||||||
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`);
|
|
||||||
});
|
|
||||||
@@ -1,12 +1,88 @@
|
|||||||
import { migrate } from "drizzle-orm/bun-sqlite/migrator";
|
import { drizzle } from "drizzle-orm/better-sqlite3";
|
||||||
import { drizzle } from "drizzle-orm/bun-sqlite";
|
import { migrate } from "drizzle-orm/better-sqlite3/migrator";
|
||||||
import * as schema from "../database/schema";
|
import Database from "better-sqlite3";
|
||||||
|
import { users, tokens, preferences } from "../database/schema";
|
||||||
|
import { existsSync, readFileSync } from "node:fs";
|
||||||
|
|
||||||
export default defineNitroPlugin(async () => {
|
export default defineNitroPlugin(async () => {
|
||||||
const config = useRuntimeConfig();
|
const db = useDrizzle();
|
||||||
const db = drizzle(config.databaseUrl, { schema });
|
|
||||||
|
|
||||||
console.log("Running database migrations...");
|
migrate(db, { migrationsFolder: "./server/database/migrations" });
|
||||||
await migrate(db, { migrationsFolder: "./server/database/migrations" });
|
console.log("Database migrations applied");
|
||||||
console.log("Database migrations complete");
|
|
||||||
|
const feedPath = "./tmp/feed.json";
|
||||||
|
|
||||||
|
if (existsSync(feedPath)) {
|
||||||
|
const feed = JSON.parse(readFileSync(feedPath, "utf-8"));
|
||||||
|
console.log(`Importing ${feed.length} users from feed.json`);
|
||||||
|
|
||||||
|
for (const entry of feed) {
|
||||||
|
const userId = String(entry.user.id);
|
||||||
|
const createdAt =
|
||||||
|
entry.user.created_at && entry.user.created_at !== "\r"
|
||||||
|
? new Date(entry.user.created_at)
|
||||||
|
: new Date();
|
||||||
|
|
||||||
|
const userData = {
|
||||||
|
id: userId,
|
||||||
|
name: entry.user.name || "Unknown",
|
||||||
|
avatar: entry.user.avatar || null,
|
||||||
|
city: entry.user.city || null,
|
||||||
|
country:
|
||||||
|
typeof entry.user.country === "string" && entry.user.country !== "\r"
|
||||||
|
? entry.user.country
|
||||||
|
: null,
|
||||||
|
sex:
|
||||||
|
typeof entry.user.sex === "string" && entry.user.sex !== "\r"
|
||||||
|
? entry.user.sex
|
||||||
|
: null,
|
||||||
|
weight: Number(entry.user.weight) || null,
|
||||||
|
createdAt,
|
||||||
|
};
|
||||||
|
|
||||||
|
await db
|
||||||
|
.insert(users)
|
||||||
|
.values(userData)
|
||||||
|
.onConflictDoUpdate({
|
||||||
|
target: users.id,
|
||||||
|
set: { ...userData },
|
||||||
|
});
|
||||||
|
|
||||||
|
const tokenData = {
|
||||||
|
userId: userId,
|
||||||
|
refreshToken: entry.token.refresh_token || null,
|
||||||
|
accessToken: entry.token.access_token || null,
|
||||||
|
expiresAt: new Date(entry.token.expires_at),
|
||||||
|
};
|
||||||
|
|
||||||
|
await db
|
||||||
|
.insert(tokens)
|
||||||
|
.values(tokenData)
|
||||||
|
.onConflictDoUpdate({
|
||||||
|
target: tokens.userId,
|
||||||
|
set: { ...tokenData },
|
||||||
|
});
|
||||||
|
|
||||||
|
const prefsData = {
|
||||||
|
userId,
|
||||||
|
data: {
|
||||||
|
enabled: entry.preferences.enabled ?? true,
|
||||||
|
language: entry.preferences.language || "English",
|
||||||
|
units: entry.preferences.units || "Metric",
|
||||||
|
tone: entry.preferences.tone || [],
|
||||||
|
highlights: entry.preferences.highlights || [],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
await db
|
||||||
|
.insert(preferences)
|
||||||
|
.values(prefsData)
|
||||||
|
.onConflictDoUpdate({
|
||||||
|
target: preferences.userId,
|
||||||
|
set: { ...prefsData },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`Successfully imported ${feed.length} users`);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,11 +1,4 @@
|
|||||||
import { drizzle } from "drizzle-orm/bun-sqlite";
|
import { drizzle } from "drizzle-orm/better-sqlite3";
|
||||||
import { eq as _eq, and as _and, or as _or, sql as _sql } from "drizzle-orm";
|
|
||||||
|
|
||||||
export const sql = _sql;
|
|
||||||
export const eq = _eq;
|
|
||||||
export const and = _and;
|
|
||||||
export const or = _or;
|
|
||||||
|
|
||||||
import * as schema from "../database/schema";
|
import * as schema from "../database/schema";
|
||||||
|
|
||||||
export const tables = schema;
|
export const tables = schema;
|
||||||
|
|||||||
Reference in New Issue
Block a user