diff --git a/db/index.ts b/db/index.ts index 07835ba..beaea0e 100644 --- a/db/index.ts +++ b/db/index.ts @@ -3,4 +3,4 @@ import { neon } from "@neondatabase/serverless"; import { drizzle } from "drizzle-orm/neon-http"; const sql = neon(env.DATABASE_URI); -export const db = drizzle({ client: sql }); +export const db = drizzle({ client: sql, logger: true }); diff --git a/db/migrate.ts b/db/migrate.ts index dfb069d..47b4ba7 100644 --- a/db/migrate.ts +++ b/db/migrate.ts @@ -1,9 +1,9 @@ -/* eslint-disable no-console */ import { env } from "@/lib/env"; - import { drizzle } from "drizzle-orm/postgres-js"; import { migrate } from "drizzle-orm/postgres-js/migrator"; +import pino from "pino"; import postgres from "postgres"; +const logger = pino({ transport: { target: "pino-pretty" } }); const runMigrate = async () => { if (!env.DATABASE_URI) { @@ -12,9 +12,9 @@ const runMigrate = async () => { const connection = postgres(env.DATABASE_URI, { max: 1 }); - const db = drizzle(connection); + const db = drizzle(connection, { logger: true }); - console.log("⏳ Running migrations..."); + logger.info("Running migrations..."); const start = Date.now(); @@ -22,13 +22,13 @@ const runMigrate = async () => { const end = Date.now(); - console.log("✅ Migrations completed in", end - start, "ms"); - + logger.info("Migrations completed in %dms", end - start); process.exit(0); }; runMigrate().catch((err: unknown) => { - console.error("❌ Migration failed"); - console.error(err); + const error = err as Error; + logger.error("❌ Migration failed"); + logger.error(error.message); process.exit(1); }); diff --git a/db/schema/resources.ts b/db/schema/resources.ts index 389fdbc..394c155 100644 --- a/db/schema/resources.ts +++ b/db/schema/resources.ts @@ -1,5 +1,5 @@ import { sql } from "drizzle-orm"; -import { text, varchar, timestamp, pgTable } from "drizzle-orm/pg-core"; +import { pgTable, text, timestamp, varchar } from "drizzle-orm/pg-core"; import { createSelectSchema } from "drizzle-zod"; import { z } from "zod"; @@ -11,10 +11,10 @@ export const resources = pgTable("resources", { .$defaultFn(() => nanoid()), content: text("content").notNull(), - createdAt: timestamp("created_at") + createdAt: timestamp("created_at", { withTimezone: true }) .notNull() .default(sql`now()`), - updatedAt: timestamp("updated_at") + updatedAt: timestamp("updated_at", { withTimezone: true }) .notNull() .default(sql`now()`), }); diff --git a/package.json b/package.json index c25ef7e..d16419a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "agent-dot", - "version": "1.5.2", + "version": "1.5.3", "private": true, "scripts": { "dev": "next dev --turbopack", @@ -41,7 +41,9 @@ "drizzle-zod": "^0.8.2", "framer-motion": "^12.23.6", "lucide-react": "^0.525.0", + "nanoid": "^5.1.5", "next": "15.4.2", + "pino": "^9.7.0", "polkadot-api": "^1.15.0", "postgres": "^3.4.7", "react": "^19.1.0", @@ -73,6 +75,7 @@ "eslint-plugin-prettier": "^5.5.3", "husky": "^9.1.7", "lint-staged": "^16.1.2", + "pino-pretty": "^13.0.0", "prettier": "^3.6.2", "prettier-plugin-tailwindcss": "^0.6.14", "tailwindcss": "^4.1.11", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c21f0f8..48481d5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -61,6 +61,9 @@ importers: next: specifier: 15.4.2 version: 15.4.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + pino: + specifier: ^9.7.0 + version: 9.7.0 polkadot-api: specifier: ^1.15.0 version: 1.15.0(jiti@2.4.2)(postcss@8.5.6)(rxjs@7.8.2)(tsx@4.20.3)(yaml@2.8.0) @@ -149,6 +152,9 @@ importers: lint-staged: specifier: ^16.1.2 version: 16.1.2 + pino-pretty: + specifier: ^13.0.0 + version: 13.0.0 prettier: specifier: ^3.6.2 version: 3.6.2 @@ -2798,6 +2804,13 @@ packages: } engines: { node: ">= 0.4" } + atomic-sleep@1.0.0: + resolution: + { + integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==, + } + engines: { node: ">=8.0.0" } + available-typed-arrays@1.0.7: resolution: { @@ -3158,6 +3171,12 @@ packages: } engines: { node: ">= 0.4" } + dateformat@4.6.3: + resolution: + { + integrity: sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==, + } + debug@3.2.7: resolution: { @@ -3390,6 +3409,12 @@ packages: integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==, } + end-of-stream@1.4.5: + resolution: + { + integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==, + } + enhanced-resolve@5.18.2: resolution: { @@ -3717,6 +3742,12 @@ packages: } engines: { node: ^18.19.0 || >=20.5.0 } + fast-copy@3.0.2: + resolution: + { + integrity: sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ==, + } + fast-deep-equal@3.1.3: resolution: { @@ -3755,6 +3786,19 @@ packages: integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==, } + fast-redact@3.5.0: + resolution: + { + integrity: sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==, + } + engines: { node: ">=6" } + + fast-safe-stringify@2.1.1: + resolution: + { + integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==, + } + fast-uri@3.0.6: resolution: { @@ -4068,6 +4112,12 @@ packages: } engines: { node: ">= 0.4" } + help-me@5.0.0: + resolution: + { + integrity: sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==, + } + hosted-git-info@7.0.2: resolution: { @@ -5021,6 +5071,19 @@ packages: } engines: { node: ">= 0.4" } + on-exit-leak-free@2.1.2: + resolution: + { + integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==, + } + engines: { node: ">=14.0.0" } + + once@1.4.0: + resolution: + { + integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==, + } + onetime@7.0.0: resolution: { @@ -5206,6 +5269,32 @@ packages: engines: { node: ">=0.10" } hasBin: true + pino-abstract-transport@2.0.0: + resolution: + { + integrity: sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==, + } + + pino-pretty@13.0.0: + resolution: + { + integrity: sha512-cQBBIVG3YajgoUjo1FdKVRX6t9XPxwB9lcNJVD5GCnNM4Y6T12YYx8c6zEejxQsU0wrg9TwmDulcE9LR7qcJqA==, + } + hasBin: true + + pino-std-serializers@7.0.0: + resolution: + { + integrity: sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==, + } + + pino@9.7.0: + resolution: + { + integrity: sha512-vnMCM6xZTb1WDmLvtG2lE/2p+t9hDEIvTWJsu6FejkE62vB7gDhvzrpFR4Cw2to+9JNQxVnkAKVPA1KPB98vWg==, + } + hasBin: true + pirates@4.0.7: resolution: { @@ -5398,12 +5487,24 @@ packages: } engines: { node: ">=18" } + process-warning@5.0.0: + resolution: + { + integrity: sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==, + } + prop-types@15.8.1: resolution: { integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==, } + pump@3.0.3: + resolution: + { + integrity: sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==, + } + punycode@2.3.1: resolution: { @@ -5417,6 +5518,12 @@ packages: integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==, } + quick-format-unescaped@4.0.4: + resolution: + { + integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==, + } + react-dom@19.1.0: resolution: { @@ -5508,6 +5615,13 @@ packages: } engines: { node: ">= 14.18.0" } + real-require@0.2.0: + resolution: + { + integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==, + } + engines: { node: ">= 12.13.0" } + reflect.getprototypeof@1.0.10: resolution: { @@ -5632,6 +5746,13 @@ packages: } engines: { node: ">= 0.4" } + safe-stable-stringify@2.5.0: + resolution: + { + integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==, + } + engines: { node: ">=10" } + scale-ts@1.6.1: resolution: { @@ -5644,6 +5765,12 @@ packages: integrity: sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==, } + secure-json-parse@2.7.0: + resolution: + { + integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==, + } + semver@6.3.1: resolution: { @@ -5762,6 +5889,12 @@ packages: integrity: sha512-0GtHgxOs1VGs+WzpUgTQ52Zg92/q4mnIPEl+smArI4pis6aduQ6ZiXRllbDafsIb18wWYsxaBLNjBkNOB8xBrw==, } + sonic-boom@4.2.0: + resolution: + { + integrity: sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==, + } + sonner@2.0.6: resolution: { @@ -6051,6 +6184,12 @@ packages: integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==, } + thread-stream@3.1.0: + resolution: + { + integrity: sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==, + } + through@2.3.8: resolution: { @@ -6396,6 +6535,12 @@ packages: } engines: { node: ">=18" } + wrappy@1.0.2: + resolution: + { + integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==, + } + write-file-atomic@5.0.1: resolution: { @@ -8036,6 +8181,8 @@ snapshots: async-function@1.0.0: {} + atomic-sleep@1.0.0: {} + available-typed-arrays@1.0.7: dependencies: possible-typed-array-names: 1.1.0 @@ -8231,6 +8378,8 @@ snapshots: es-errors: 1.3.0 is-data-view: 1.0.2 + dateformat@4.6.3: {} + debug@3.2.7: dependencies: ms: 2.1.3 @@ -8305,6 +8454,10 @@ snapshots: emoji-regex@9.2.2: {} + end-of-stream@1.4.5: + dependencies: + once: 1.4.0 + enhanced-resolve@5.18.2: dependencies: graceful-fs: 4.2.11 @@ -8711,6 +8864,8 @@ snapshots: strip-final-newline: 4.0.0 yoctocolors: 2.1.1 + fast-copy@3.0.2: {} + fast-deep-equal@3.1.3: {} fast-diff@1.3.0: {} @@ -8735,6 +8890,10 @@ snapshots: fast-levenshtein@2.0.6: {} + fast-redact@3.5.0: {} + + fast-safe-stringify@2.1.1: {} + fast-uri@3.0.6: {} fastq@1.19.1: @@ -8918,6 +9077,8 @@ snapshots: dependencies: function-bind: 1.1.2 + help-me@5.0.0: {} + hosted-git-info@7.0.2: dependencies: lru-cache: 10.4.3 @@ -9424,6 +9585,12 @@ snapshots: define-properties: 1.2.1 es-object-atoms: 1.1.1 + on-exit-leak-free@2.1.2: {} + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + onetime@7.0.0: dependencies: mimic-function: 5.0.1 @@ -9529,6 +9696,42 @@ snapshots: pidtree@0.6.0: {} + pino-abstract-transport@2.0.0: + dependencies: + split2: 4.2.0 + + pino-pretty@13.0.0: + dependencies: + colorette: 2.0.20 + dateformat: 4.6.3 + fast-copy: 3.0.2 + fast-safe-stringify: 2.1.1 + help-me: 5.0.0 + joycon: 3.1.1 + minimist: 1.2.8 + on-exit-leak-free: 2.1.2 + pino-abstract-transport: 2.0.0 + pump: 3.0.3 + secure-json-parse: 2.7.0 + sonic-boom: 4.2.0 + strip-json-comments: 3.1.1 + + pino-std-serializers@7.0.0: {} + + pino@9.7.0: + dependencies: + atomic-sleep: 1.0.0 + fast-redact: 3.5.0 + on-exit-leak-free: 2.1.2 + pino-abstract-transport: 2.0.0 + pino-std-serializers: 7.0.0 + process-warning: 5.0.0 + quick-format-unescaped: 4.0.4 + real-require: 0.2.0 + safe-stable-stringify: 2.5.0 + sonic-boom: 4.2.0 + thread-stream: 3.1.0 + pirates@4.0.7: {} pkg-types@1.3.1: @@ -9621,16 +9824,25 @@ snapshots: dependencies: parse-ms: 4.0.0 + process-warning@5.0.0: {} + prop-types@15.8.1: dependencies: loose-envify: 1.4.0 object-assign: 4.1.1 react-is: 16.13.1 + pump@3.0.3: + dependencies: + end-of-stream: 1.4.5 + once: 1.4.0 + punycode@2.3.1: {} queue-microtask@1.2.3: {} + quick-format-unescaped@4.0.4: {} + react-dom@19.1.0(react@19.1.0): dependencies: react: 19.1.0 @@ -9685,6 +9897,8 @@ snapshots: readdirp@4.1.2: {} + real-require@0.2.0: {} + reflect.getprototypeof@1.0.10: dependencies: call-bind: 1.0.8 @@ -9789,10 +10003,14 @@ snapshots: es-errors: 1.3.0 is-regex: 1.2.1 + safe-stable-stringify@2.5.0: {} + scale-ts@1.6.1: {} scheduler@0.26.0: {} + secure-json-parse@2.7.0: {} + semver@6.3.1: {} semver@7.7.2: {} @@ -9907,6 +10125,10 @@ snapshots: - bufferutil - utf-8-validate + sonic-boom@4.2.0: + dependencies: + atomic-sleep: 1.0.0 + sonner@2.0.6(react-dom@19.1.0(react@19.1.0))(react@19.1.0): dependencies: react: 19.1.0 @@ -10088,6 +10310,10 @@ snapshots: dependencies: any-promise: 1.3.0 + thread-stream@3.1.0: + dependencies: + real-require: 0.2.0 + through@2.3.8: {} tinyexec@0.3.2: {} @@ -10364,6 +10590,8 @@ snapshots: string-width: 7.2.0 strip-ansi: 7.1.0 + wrappy@1.0.2: {} + write-file-atomic@5.0.1: dependencies: imurmurhash: 0.1.4