From 547181d333e9bd81946472491e8cdc3a0b522f90 Mon Sep 17 00:00:00 2001 From: cheney Date: Thu, 6 Aug 2026 15:39:59 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E9=A6=96=E9=A1=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- generated/prisma/browser.ts | 10 + generated/prisma/client.ts | 10 + generated/prisma/internal/class.ts | 28 +- generated/prisma/internal/prismaNamespace.ts | 188 ++- .../prisma/internal/prismaNamespaceBrowser.ts | 52 + generated/prisma/models.ts | 2 + generated/prisma/models/Alert.ts | 1238 +++++++++++++++++ generated/prisma/models/News.ts | 1174 ++++++++++++++++ package-lock.json | 22 + package.json | 4 +- .../migration.sql | 32 + prisma/schema.prisma | 32 + readme | 5 +- scripts/fetchers/news.fetcher.js | 122 ++ scripts/refresh-indicators.cjs | 10 +- scripts/refresh-news.cjs | 12 + server/alert-engine.js | 46 + server/cron.js | 36 + server/index.js | 7 + server/routes/alerts.js | 24 + server/routes/news.js | 25 + src/pages/HomePage.jsx | 166 ++- src/styles/globals.css | 22 +- 23 files changed, 3248 insertions(+), 19 deletions(-) create mode 100644 generated/prisma/models/Alert.ts create mode 100644 generated/prisma/models/News.ts create mode 100644 prisma/migrations/20260806130000_news_and_alerts/migration.sql create mode 100644 scripts/fetchers/news.fetcher.js create mode 100644 scripts/refresh-news.cjs create mode 100644 server/alert-engine.js create mode 100644 server/cron.js create mode 100644 server/routes/alerts.js create mode 100644 server/routes/news.js diff --git a/generated/prisma/browser.ts b/generated/prisma/browser.ts index dfa08fc..3212bb9 100644 --- a/generated/prisma/browser.ts +++ b/generated/prisma/browser.ts @@ -42,6 +42,16 @@ export type Indicator = Prisma.IndicatorModel * */ export type IndicatorPoint = Prisma.IndicatorPointModel +/** + * Model News + * + */ +export type News = Prisma.NewsModel +/** + * Model Alert + * + */ +export type Alert = Prisma.AlertModel /** * Model Econ_SowInventory * diff --git a/generated/prisma/client.ts b/generated/prisma/client.ts index 2c80d98..1786db5 100644 --- a/generated/prisma/client.ts +++ b/generated/prisma/client.ts @@ -66,6 +66,16 @@ export type Indicator = Prisma.IndicatorModel * */ export type IndicatorPoint = Prisma.IndicatorPointModel +/** + * Model News + * + */ +export type News = Prisma.NewsModel +/** + * Model Alert + * + */ +export type Alert = Prisma.AlertModel /** * Model Econ_SowInventory * diff --git a/generated/prisma/internal/class.ts b/generated/prisma/internal/class.ts index c79518b..19bd89a 100644 --- a/generated/prisma/internal/class.ts +++ b/generated/prisma/internal/class.ts @@ -20,7 +20,7 @@ const config: runtime.GetPrismaClientConfig = { "clientVersion": "7.7.0", "engineVersion": "75cbdc1eb7150937890ad5465d861175c6624711", "activeProvider": "mysql", - "inlineSchema": "// This is your Prisma schema file,\n// learn more about it in the docs: https://pris.ly/d/prisma-schema\n\n// Get a free hosted Postgres database in seconds: `npx create-db`\n\ngenerator client {\n provider = \"prisma-client\"\n output = \"../generated/prisma\"\n}\n\ndatasource db {\n provider = \"mysql\"\n}\n\nmodel User {\n id Int @id @default(autoincrement())\n name String\n email String @unique\n password String\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\nmodel Article {\n id Int @id @default(autoincrement())\n title String\n slug String @unique\n content String\n date String\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\nmodel Strategy {\n id Int @id @default(autoincrement())\n name String\n description String\n data Json\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\nmodel Indicator {\n id Int @id @default(autoincrement())\n name String @unique\n groupName String\n title String @default(\"\")\n unit String @default(\"\")\n source String @default(\"\")\n frequency String @default(\"month\") // year | quarter | month | day\n hidden Boolean @default(false) // true = 数据/脚本保留, 但不在前端展示\n points IndicatorPoint[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\nmodel IndicatorPoint {\n id Int @id @default(autoincrement())\n indicatorId Int\n indicator Indicator @relation(fields: [indicatorId], references: [id], onDelete: Cascade)\n period String // \"2024\" | \"2024-Q1\" | \"2024-01\" | \"2024-01-15\"\n value Float\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@unique([indicatorId, period])\n}\n\nmodel Econ_SowInventory {\n id Int @id @default(autoincrement())\n month String @unique\n inventory Int // 能繁母猪数量(万头)\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\nmodel ScraperCache {\n id Int @id @default(autoincrement())\n scraperName String @unique // 爬虫名称,如:sow-inventory\n lastDataHash String? // 上次数据指纹\n lastUpdateAt DateTime // 上次更新时间\n metadata Json? // 其他元数据\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n", + "inlineSchema": "// This is your Prisma schema file,\n// learn more about it in the docs: https://pris.ly/d/prisma-schema\n\n// Get a free hosted Postgres database in seconds: `npx create-db`\n\ngenerator client {\n provider = \"prisma-client\"\n output = \"../generated/prisma\"\n}\n\ndatasource db {\n provider = \"mysql\"\n}\n\nmodel User {\n id Int @id @default(autoincrement())\n name String\n email String @unique\n password String\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\nmodel Article {\n id Int @id @default(autoincrement())\n title String\n slug String @unique\n content String\n date String\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\nmodel Strategy {\n id Int @id @default(autoincrement())\n name String\n description String\n data Json\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\nmodel Indicator {\n id Int @id @default(autoincrement())\n name String @unique\n groupName String\n title String @default(\"\")\n unit String @default(\"\")\n source String @default(\"\")\n frequency String @default(\"month\") // year | quarter | month | day\n hidden Boolean @default(false) // true = 数据/脚本保留, 但不在前端展示\n points IndicatorPoint[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\nmodel IndicatorPoint {\n id Int @id @default(autoincrement())\n indicatorId Int\n indicator Indicator @relation(fields: [indicatorId], references: [id], onDelete: Cascade)\n period String // \"2024\" | \"2024-Q1\" | \"2024-01\" | \"2024-01-15\"\n value Float\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@unique([indicatorId, period])\n}\n\n// 新闻: 每天 3 点由 mx_finance_search_news 拉取, 按影响大小排序, 累加多日供首页无限滚动\nmodel News {\n id Int @id @default(autoincrement())\n title String\n summary String @default(\"\")\n source String @default(\"\")\n url String @default(\"\")\n publishedAt DateTime\n impactRank Int\n createdAt DateTime @default(now())\n\n @@unique([title, publishedAt])\n @@index([publishedAt])\n}\n\n// 报警: refresh 写库时比对同 (indicatorName, period) 的跨源数据, 差异超阈值记录\nmodel Alert {\n id Int @id @default(autoincrement())\n indicatorName String\n period String\n valueA Float\n valueB Float\n sourceA String\n sourceB String\n diff Float\n diffRatio Float\n createdAt DateTime @default(now())\n\n @@index([createdAt])\n}\n\nmodel Econ_SowInventory {\n id Int @id @default(autoincrement())\n month String @unique\n inventory Int // 能繁母猪数量(万头)\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\nmodel ScraperCache {\n id Int @id @default(autoincrement())\n scraperName String @unique // 爬虫名称,如:sow-inventory\n lastDataHash String? // 上次数据指纹\n lastUpdateAt DateTime // 上次更新时间\n metadata Json? // 其他元数据\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n", "runtimeDataModel": { "models": {}, "enums": {}, @@ -32,10 +32,10 @@ const config: runtime.GetPrismaClientConfig = { } } -config.runtimeDataModel = JSON.parse("{\"models\":{\"User\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"email\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"password\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"Article\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"title\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"slug\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"content\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"date\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"Strategy\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"data\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"Indicator\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"groupName\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"title\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"unit\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"source\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"frequency\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"hidden\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"points\",\"kind\":\"object\",\"type\":\"IndicatorPoint\",\"relationName\":\"IndicatorToIndicatorPoint\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"IndicatorPoint\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"indicatorId\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"indicator\",\"kind\":\"object\",\"type\":\"Indicator\",\"relationName\":\"IndicatorToIndicatorPoint\"},{\"name\":\"period\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"value\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"Econ_SowInventory\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"month\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"inventory\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"ScraperCache\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"scraperName\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"lastDataHash\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"lastUpdateAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"metadata\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null}},\"enums\":{},\"types\":{}}") +config.runtimeDataModel = JSON.parse("{\"models\":{\"User\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"email\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"password\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"Article\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"title\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"slug\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"content\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"date\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"Strategy\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"data\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"Indicator\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"groupName\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"title\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"unit\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"source\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"frequency\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"hidden\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"points\",\"kind\":\"object\",\"type\":\"IndicatorPoint\",\"relationName\":\"IndicatorToIndicatorPoint\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"IndicatorPoint\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"indicatorId\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"indicator\",\"kind\":\"object\",\"type\":\"Indicator\",\"relationName\":\"IndicatorToIndicatorPoint\"},{\"name\":\"period\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"value\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"News\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"title\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"summary\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"source\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"url\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"publishedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"impactRank\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"Alert\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"indicatorName\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"period\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"valueA\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"valueB\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"sourceA\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"sourceB\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"diff\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"diffRatio\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"Econ_SowInventory\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"month\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"inventory\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"ScraperCache\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"scraperName\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"lastDataHash\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"lastUpdateAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"metadata\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null}},\"enums\":{},\"types\":{}}") config.parameterizationSchema = { - strings: JSON.parse("[\"where\",\"User.findUnique\",\"User.findUniqueOrThrow\",\"orderBy\",\"cursor\",\"User.findFirst\",\"User.findFirstOrThrow\",\"User.findMany\",\"data\",\"User.createOne\",\"User.createMany\",\"User.updateOne\",\"User.updateMany\",\"create\",\"update\",\"User.upsertOne\",\"User.deleteOne\",\"User.deleteMany\",\"having\",\"_count\",\"_avg\",\"_sum\",\"_min\",\"_max\",\"User.groupBy\",\"User.aggregate\",\"Article.findUnique\",\"Article.findUniqueOrThrow\",\"Article.findFirst\",\"Article.findFirstOrThrow\",\"Article.findMany\",\"Article.createOne\",\"Article.createMany\",\"Article.updateOne\",\"Article.updateMany\",\"Article.upsertOne\",\"Article.deleteOne\",\"Article.deleteMany\",\"Article.groupBy\",\"Article.aggregate\",\"Strategy.findUnique\",\"Strategy.findUniqueOrThrow\",\"Strategy.findFirst\",\"Strategy.findFirstOrThrow\",\"Strategy.findMany\",\"Strategy.createOne\",\"Strategy.createMany\",\"Strategy.updateOne\",\"Strategy.updateMany\",\"Strategy.upsertOne\",\"Strategy.deleteOne\",\"Strategy.deleteMany\",\"Strategy.groupBy\",\"Strategy.aggregate\",\"indicator\",\"points\",\"Indicator.findUnique\",\"Indicator.findUniqueOrThrow\",\"Indicator.findFirst\",\"Indicator.findFirstOrThrow\",\"Indicator.findMany\",\"Indicator.createOne\",\"Indicator.createMany\",\"Indicator.updateOne\",\"Indicator.updateMany\",\"Indicator.upsertOne\",\"Indicator.deleteOne\",\"Indicator.deleteMany\",\"Indicator.groupBy\",\"Indicator.aggregate\",\"IndicatorPoint.findUnique\",\"IndicatorPoint.findUniqueOrThrow\",\"IndicatorPoint.findFirst\",\"IndicatorPoint.findFirstOrThrow\",\"IndicatorPoint.findMany\",\"IndicatorPoint.createOne\",\"IndicatorPoint.createMany\",\"IndicatorPoint.updateOne\",\"IndicatorPoint.updateMany\",\"IndicatorPoint.upsertOne\",\"IndicatorPoint.deleteOne\",\"IndicatorPoint.deleteMany\",\"IndicatorPoint.groupBy\",\"IndicatorPoint.aggregate\",\"Econ_SowInventory.findUnique\",\"Econ_SowInventory.findUniqueOrThrow\",\"Econ_SowInventory.findFirst\",\"Econ_SowInventory.findFirstOrThrow\",\"Econ_SowInventory.findMany\",\"Econ_SowInventory.createOne\",\"Econ_SowInventory.createMany\",\"Econ_SowInventory.updateOne\",\"Econ_SowInventory.updateMany\",\"Econ_SowInventory.upsertOne\",\"Econ_SowInventory.deleteOne\",\"Econ_SowInventory.deleteMany\",\"Econ_SowInventory.groupBy\",\"Econ_SowInventory.aggregate\",\"ScraperCache.findUnique\",\"ScraperCache.findUniqueOrThrow\",\"ScraperCache.findFirst\",\"ScraperCache.findFirstOrThrow\",\"ScraperCache.findMany\",\"ScraperCache.createOne\",\"ScraperCache.createMany\",\"ScraperCache.updateOne\",\"ScraperCache.updateMany\",\"ScraperCache.upsertOne\",\"ScraperCache.deleteOne\",\"ScraperCache.deleteMany\",\"ScraperCache.groupBy\",\"ScraperCache.aggregate\",\"AND\",\"OR\",\"NOT\",\"id\",\"scraperName\",\"lastDataHash\",\"lastUpdateAt\",\"metadata\",\"createdAt\",\"updatedAt\",\"equals\",\"string_contains\",\"string_starts_with\",\"string_ends_with\",\"array_starts_with\",\"array_ends_with\",\"array_contains\",\"lt\",\"lte\",\"gt\",\"gte\",\"not\",\"in\",\"notIn\",\"contains\",\"startsWith\",\"endsWith\",\"search\",\"month\",\"inventory\",\"indicatorId\",\"period\",\"value\",\"name\",\"groupName\",\"title\",\"unit\",\"source\",\"frequency\",\"hidden\",\"every\",\"some\",\"none\",\"indicatorId_period\",\"description\",\"slug\",\"content\",\"date\",\"email\",\"password\",\"is\",\"isNot\",\"_relevance\",\"connectOrCreate\",\"upsert\",\"createMany\",\"set\",\"disconnect\",\"delete\",\"connect\",\"updateMany\",\"deleteMany\",\"increment\",\"decrement\",\"multiply\",\"divide\"]"), - graph: "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AQEAAAABjQECAAAAAQEIAACAAQAwBXMCAN0BACF4QADcAQAheUAA3AEAIYwBAQDaAQAhjQECAN0BACECAAAAdgAgCAAAggEAIAVzAgDdAQAheEAA3AEAIXlAANwBACGMAQEA2gEAIY0BAgDdAQAhAgAAAHkAIAgAAIQBACADAAAAdgAgDQAAfgAgDgAAggEAIAEAAAB2ACABAAAAeQAgBRMAAN8BACAUAADgAQAgFQAA4wEAIBYAAOIBACAXAADhAQAgCHAAALsBADBxAACKAQAQcgAAuwEAMHMCAKUBACF4QACoAQAheUAAqAEAIYwBAQCmAQAhjQECAKUBACEDAAAAeQAgAwAAiQEAMBIAAIoBACADAAAAeQAgAwAAegAwBAAAdgAgCnAAALUBADBxAACQAQAQcgAAtQEAMHMCAAAAAXQBAAAAAXUBALgBACF2QAC5AQAhdwAAugEAIHhAALkBACF5QAC5AQAhAQAAAI0BACABAAAAjQEAIApwAAC1AQAwcQAAkAEAEHIAALUBADBzAgC2AQAhdAEAtwEAIXUBALgBACF2QAC5AQAhdwAAugEAIHhAALkBACF5QAC5AQAhA3UAANQBACB3AADUAQAgpAEAAN4BACADAAAAkAEAIAMAAJEBADAEAACNAQAgAwAAAJABACADAACRAQAwBAAAjQEAIAMAAACQAQAgAwAAkQEAMAQAAI0BACAHcwIAAAABdAEAAAABdQEAAAABdkAAAAABd4AAAAABeEAAAAABeUAAAAABAQgAAJUBACAHcwIAAAABdAEAAAABdQEAAAABdkAAAAABd4AAAAABeEAAAAABeUAAAAABAQgAAJcBADAHcwIA3QEAIXQBANoBACF1AQDbAQAhdkAA3AEAIXeAAAAAAXhAANwBACF5QADcAQAhAgAAAI0BACAIAACZAQAgB3MCAN0BACF0AQDaAQAhdQEA2wEAIXZAANwBACF3gAAAAAF4QADcAQAheUAA3AEAIQIAAACQAQAgCAAAmwEAIAMAAACNAQAgDQAAlQEAIA4AAJkBACABAAAAjQEAIAEAAACQAQAgBxMAANUBACAUAADWAQAgFQAA2QEAIBYAANgBACAXAADXAQAgdQAA1AEAIHcAANQBACAKcAAApAEAMHEAAKEBABByAACkAQAwcwIApQEAIXQBAKYBACF1AQCnAQAhdkAAqAEAIXcAAKkBACB4QACoAQAheUAAqAEAIQMAAACQAQAgAwAAoAEAMBIAAKEBACADAAAAkAEAIAMAAJEBADAEAACNAQAgCnAAAKQBADBxAAChAQAQcgAApAEAMHMCAKUBACF0AQCmAQAhdQEApwEAIXZAAKgBACF3AACpAQAgeEAAqAEAIXlAAKgBACENEwAArQEAIBQAALQBACAVAACtAQAgFgAArQEAIBcAAK0BACB6AgAAAAGBAQIAAAABggECAAAAAYMBAgAAAAGEAQIAAAABhQECALMBACGGAQIAAAAEhwECAAAABA8TAACtAQAgFgAAsgEAIBcAALIBACB6AQAAAAGBAQEAAAABggEBAAAAAYMBAQAAAAGEAQEAAAABhQEBALEBACGGAQEAAAAEhwEBAAAABIgBAQAAAAGJAQEAAAABigEBAAAAAYsBAQAAAAEPEwAAqgEAIBYAALABACAXAACwAQAgegEAAAABgQEBAAAAAYIBAQAAAAGDAQEAAAABhAEBAAAAAYUBAQCvAQAhhgEBAAAABYcBAQAAAAWIAQEAAAABiQEBAAAAAYoBAQAAAAGLAQEAAAABCxMAAK0BACAWAACuAQAgFwAArgEAIHpAAAAAAYEBQAAAAAGCAUAAAAABgwFAAAAAAYQBQAAAAAGFAUAArAEAIYYBQAAAAASHAUAAAAAEDxMAAKoBACAWAACrAQAgFwAAqwEAIHqAAAAAAXsBAAAAAXwBAAAAAX0BAAAAAX6AAAAAAX-AAAAAAYABgAAAAAGBAYAAAAABggGAAAAAAYMBgAAAAAGEAYAAAAABhQGAAAAAAQh6AgAAAAGBAQIAAAABggECAAAAAYMBAgAAAAGEAQIAAAABhQECAKoBACGGAQIAAAAFhwECAAAABQx6gAAAAAF7AQAAAAF8AQAAAAF9AQAAAAF-gAAAAAF_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_AQAhhgEIAAAABIcBCAAAAAQNcAAAwAEAMHEAAF8AEHIAAMABADBzAgClAQAheEAAqAEAIXlAAKgBACGRAQEApgEAIZIBAQCmAQAhkwEBAKYBACGUAQEApgEAIZUBAQCmAQAhlgEBAKYBACGXASAAwQEAIQUTAACtAQAgFgAAwwEAIBcAAMMBACB6IAAAAAGFASAAwgEAIQUTAACtAQAgFgAAwwEAIBcAAMMBACB6IAAAAAGFASAAwgEAIQJ6IAAAAAGFASAAwwEAIQ43AADGAQAgcAAAxAEAMHEAAE4AEHIAAMQBADBzAgC2AQAheEAAuQEAIXlAALkBACGRAQEAtwEAIZIBAQC3AQAhkwEBALcBACGUAQEAtwEAIZUBAQC3AQAhlgEBALcBACGXASAAxQEAIQJ6IAAAAAGFASAAwwEAIQOYAQAASAAgmQEAAEgAIJoBAABIACACjgECAAAAAY8BAQAAAAEKNgAAygEAIHAAAMgBADBxAABIABByAADIAQAwcwIAtgEAIXhAALkBACF5QAC5AQAhjgECALYBACGPAQEAtwEAIZABCADJAQAhCHoIAAAAAYEBCAAAAAGCAQgAAAABgwEIAAAAAYQBCAAAAAGFAQgAtAEAIYYBCAAAAASHAQgAAAAEEDcAAMYBACBwAADEAQAwcQAATgAQcgAAxAEAMHMCALYBACF4QAC5AQAheUAAuQEAIZEBAQC3AQAhkgEBALcBACGTAQEAtwEAIZQBAQC3AQAhlQEBALcBACGWAQEAtwEAIZcBIADFAQAhogEAAE4AIKMBAABOACAJCAAAzAEAIHAAAMsBADBxAABDABByAADLAQAwcwIApQEAIXhAAKgBACF5QACoAQAhkQEBAKYBACGcAQEApgEAIQ8TAACtAQAgFgAAzQEAIBcAAM0BACB6gAAAAAF7AQAAAAF8AQAAAAF9AQAAAAF-gAAAAAF_gAAAAAGAAYAAAAABgQGAAAAAAYIBgAAAAAGDAYAAAAABhAGAAAAAAYUBgAAAAAEMeoAAAAABewEAAAABfAEAAAABfQEAAAABfoAAAAABf4AAAAABgAGAAAAAAYEBgAAAAAGCAYAAAAABgwGAAAAAAYQBgAAAAAGFAYAAAAABCQgAAM8BACBwAADOAQAwcQAAMgAQcgAAzgEAMHMCALYBACF4QAC5AQAheUAAuQEAIZEBAQC3AQAhnAEBALcBACEMeoAAAAABewEAAAABfAEAAAABfQEAAAABfoAAAAABf4AAAAABgAGAAAAAAYEBgAAAAAGCAYAAAAABgwGAAAAAAYQBgAAAAAGFAYAAAAABCnAAANABADBxAAAsABByAADQAQAwcwIApQEAIXhAAKgBACF5QACoAQAhkwEBAKYBACGdAQEApgEAIZ4BAQCmAQAhnwEBAKYBACEKcAAA0QEAMHEAABsAEHIAANEBADBzAgC2AQAheEAAuQEAIXlAALkBACGTAQEAtwEAIZ0BAQC3AQAhngEBALcBACGfAQEAtwEAIQlwAADSAQAwcQAAFQAQcgAA0gEAMHMCAKUBACF4QACoAQAheUAAqAEAIZEBAQCmAQAhoAEBAKYBACGhAQEApgEAIQlwAADTAQAwcQAABAAQcgAA0wEAMHMCALYBACF4QAC5AQAheUAAuQEAIZEBAQC3AQAhoAEBALcBACGhAQEAtwEAIQAAAAAAAAGoAQEAAAABAagBAQAAAAEBqAFAAAAAAQWoAQIAAAABrgECAAAAAa8BAgAAAAGwAQIAAAABsQECAAAAAQGLAQEAAAABAAAAAAABiwEBAAAAAQAAAAAABagBCAAAAAGuAQgAAAABrwEIAAAAAbABCAAAAAGxAQgAAAABBQ0AAJgCACAOAACbAgAgpQEAAJkCACCmAQAAmgIAIKsBAABGACADDQAAmAIAIKUBAACZAgAgqwEAAEYAIAAAAAAAAagBIAAAAAELDQAA9AEAMA4AAPkBADClAQAA9QEAMKYBAAD2AQAwpwEAAPcBACCoAQAA-AEAMKkBAAD4AQAwqgEAAPgBADCrAQAA-AEAMKwBAAD6AQAwrQEAAPsBADAFcwIAAAABeEAAAAABeUAAAAABjwEBAAAAAZABCAAAAAECAAAASgAgDQAA_wEAIAMAAABKACANAAD_AQAgDgAA_gEAIAEIAACXAgAwCzYAAMoBACBwAADIAQAwcQAASAAQcgAAyAEAMHMCAAAAAXhAALkBACF5QAC5AQAhjgECALYBACGPAQEAtwEAIZABCADJAQAhmwEAAMcBACACAAAASgAgCAAA_gEAIAIAAAD8AQAgCAAA_QEAIAlwAAD7AQAwcQAA_AEAEHIAAPsBADBzAgC2AQAheEAAuQEAIXlAALkBACGOAQIAtgEAIY8BAQC3AQAhkAEIAMkBACEJcAAA-wEAMHEAAPwBABByAAD7AQAwcwIAtgEAIXhAALkBACF5QAC5AQAhjgECALYBACGPAQEAtwEAIZABCADJAQAhBXMCAN0BACF4QADcAQAheUAA3AEAIY8BAQDaAQAhkAEIAOoBACEFcwIA3QEAIXhAANwBACF5QADcAQAhjwEBANoBACGQAQgA6gEAIQVzAgAAAAF4QAAAAAF5QAAAAAGPAQEAAAABkAEIAAAAAQQNAAD0AQAwpQEAAPUBADCnAQAA9wEAIKsBAAD4AQAwAAGLAQEAAAABAjcAAIECACCkAQAAggIAIAGLAQEAAAABAAAAAAABiwEBAAAAAQAAAAAAAYsBAQAAAAEAAAAAAAGLAQEAAAABBXMCAAAAAXhAAAAAAXlAAAAAAY8BAQAAAAGQAQgAAAABCnMCAAAAAXhAAAAAAXlAAAAAAZEBAQAAAAGSAQEAAAABkwEBAAAAAZQBAQAAAAGVAQEAAAABlgEBAAAAAZcBIAAAAAECAAAARgAgDQAAmAIAIAMAAABOACANAACYAgAgDgAAnAIAIAwAAABOACAIAACcAgAgcwIA3QEAIXhAANwBACF5QADcAQAhkQEBANoBACGSAQEA2gEAIZMBAQDaAQAhlAEBANoBACGVAQEA2gEAIZYBAQDaAQAhlwEgAPIBACEKcwIA3QEAIXhAANwBACF5QADcAQAhkQEBANoBACGSAQEA2gEAIZMBAQDaAQAhlAEBANoBACGVAQEA2gEAIZYBAQDaAQAhlwEgAPIBACEAAAUTAAQUAAUVAAYWAAcXAAgAAAAAAAUTAAQUAAUVAAYWAAcXAAgABRMADBQADRUADhYADxcAEAAAAAAABRMADBQADRUADhYADxcAEAAFEwAUFAAVFQAWFgAXFwAYAAAAAAAFEwAUFAAVFQAWFgAXFwAYAhMAHDdLGwE2ABoBN0wABRMAHhQAHxUAIBYAIRcAIgAAAAAABRMAHhQAHxUAIBYAIRcAIgUTACUUACYVACcWACgXACkAAAAAAAUTACUUACYVACcWACgXACkABRMALRQALhUALxYAMBcAMQAAAAAABRMALRQALhUALxYAMBcAMQAFEwA1FAA2FQA3FgA4FwA5AAAAAAAFEwA1FAA2FQA3FgA4FwA5AQIBAgMBBQYBBgcBBwgBCQoBCgwCCw4BDBACDxEBEBIBERMCGBYDGRcJGhkKGxoKHB0KHR4KHh8KHyEKICMCISUKIicCIygKJCkKJSoCJi0LJy4RKDASKTESKjQSKzUSLDYSLTgSLjoCLzwSMD4CMT8SMkASM0ECNEQTNUUZOEcaOU0aOlAaO1EaPFIaPVQaPlYCP1gaQFoCQVsaQlwaQ10CRGAdRWEjRmIbR2MbSGQbSWUbSmYbS2gbTGoCTWwbTm4CT28bUHAbUXECUnQkU3UqVHcrVXgrVnsrV3wrWH0rWX8rWoEBAluDAStchQECXYYBK16HAStfiAECYIsBLGGMATJijgEzY48BM2SSATNlkwEzZpQBM2eWATNomAECaZoBM2qcAQJrnQEzbJ4BM22fAQJuogE0b6MBOg" + strings: JSON.parse("[\"where\",\"User.findUnique\",\"User.findUniqueOrThrow\",\"orderBy\",\"cursor\",\"User.findFirst\",\"User.findFirstOrThrow\",\"User.findMany\",\"data\",\"User.createOne\",\"User.createMany\",\"User.updateOne\",\"User.updateMany\",\"create\",\"update\",\"User.upsertOne\",\"User.deleteOne\",\"User.deleteMany\",\"having\",\"_count\",\"_avg\",\"_sum\",\"_min\",\"_max\",\"User.groupBy\",\"User.aggregate\",\"Article.findUnique\",\"Article.findUniqueOrThrow\",\"Article.findFirst\",\"Article.findFirstOrThrow\",\"Article.findMany\",\"Article.createOne\",\"Article.createMany\",\"Article.updateOne\",\"Article.updateMany\",\"Article.upsertOne\",\"Article.deleteOne\",\"Article.deleteMany\",\"Article.groupBy\",\"Article.aggregate\",\"Strategy.findUnique\",\"Strategy.findUniqueOrThrow\",\"Strategy.findFirst\",\"Strategy.findFirstOrThrow\",\"Strategy.findMany\",\"Strategy.createOne\",\"Strategy.createMany\",\"Strategy.updateOne\",\"Strategy.updateMany\",\"Strategy.upsertOne\",\"Strategy.deleteOne\",\"Strategy.deleteMany\",\"Strategy.groupBy\",\"Strategy.aggregate\",\"indicator\",\"points\",\"Indicator.findUnique\",\"Indicator.findUniqueOrThrow\",\"Indicator.findFirst\",\"Indicator.findFirstOrThrow\",\"Indicator.findMany\",\"Indicator.createOne\",\"Indicator.createMany\",\"Indicator.updateOne\",\"Indicator.updateMany\",\"Indicator.upsertOne\",\"Indicator.deleteOne\",\"Indicator.deleteMany\",\"Indicator.groupBy\",\"Indicator.aggregate\",\"IndicatorPoint.findUnique\",\"IndicatorPoint.findUniqueOrThrow\",\"IndicatorPoint.findFirst\",\"IndicatorPoint.findFirstOrThrow\",\"IndicatorPoint.findMany\",\"IndicatorPoint.createOne\",\"IndicatorPoint.createMany\",\"IndicatorPoint.updateOne\",\"IndicatorPoint.updateMany\",\"IndicatorPoint.upsertOne\",\"IndicatorPoint.deleteOne\",\"IndicatorPoint.deleteMany\",\"IndicatorPoint.groupBy\",\"IndicatorPoint.aggregate\",\"News.findUnique\",\"News.findUniqueOrThrow\",\"News.findFirst\",\"News.findFirstOrThrow\",\"News.findMany\",\"News.createOne\",\"News.createMany\",\"News.updateOne\",\"News.updateMany\",\"News.upsertOne\",\"News.deleteOne\",\"News.deleteMany\",\"News.groupBy\",\"News.aggregate\",\"Alert.findUnique\",\"Alert.findUniqueOrThrow\",\"Alert.findFirst\",\"Alert.findFirstOrThrow\",\"Alert.findMany\",\"Alert.createOne\",\"Alert.createMany\",\"Alert.updateOne\",\"Alert.updateMany\",\"Alert.upsertOne\",\"Alert.deleteOne\",\"Alert.deleteMany\",\"Alert.groupBy\",\"Alert.aggregate\",\"Econ_SowInventory.findUnique\",\"Econ_SowInventory.findUniqueOrThrow\",\"Econ_SowInventory.findFirst\",\"Econ_SowInventory.findFirstOrThrow\",\"Econ_SowInventory.findMany\",\"Econ_SowInventory.createOne\",\"Econ_SowInventory.createMany\",\"Econ_SowInventory.updateOne\",\"Econ_SowInventory.updateMany\",\"Econ_SowInventory.upsertOne\",\"Econ_SowInventory.deleteOne\",\"Econ_SowInventory.deleteMany\",\"Econ_SowInventory.groupBy\",\"Econ_SowInventory.aggregate\",\"ScraperCache.findUnique\",\"ScraperCache.findUniqueOrThrow\",\"ScraperCache.findFirst\",\"ScraperCache.findFirstOrThrow\",\"ScraperCache.findMany\",\"ScraperCache.createOne\",\"ScraperCache.createMany\",\"ScraperCache.updateOne\",\"ScraperCache.updateMany\",\"ScraperCache.upsertOne\",\"ScraperCache.deleteOne\",\"ScraperCache.deleteMany\",\"ScraperCache.groupBy\",\"ScraperCache.aggregate\",\"AND\",\"OR\",\"NOT\",\"id\",\"scraperName\",\"lastDataHash\",\"lastUpdateAt\",\"metadata\",\"createdAt\",\"updatedAt\",\"equals\",\"string_contains\",\"string_starts_with\",\"string_ends_with\",\"array_starts_with\",\"array_ends_with\",\"array_contains\",\"lt\",\"lte\",\"gt\",\"gte\",\"not\",\"in\",\"notIn\",\"contains\",\"startsWith\",\"endsWith\",\"search\",\"month\",\"inventory\",\"indicatorName\",\"period\",\"valueA\",\"valueB\",\"sourceA\",\"sourceB\",\"diff\",\"diffRatio\",\"title\",\"summary\",\"source\",\"url\",\"publishedAt\",\"impactRank\",\"title_publishedAt\",\"indicatorId\",\"value\",\"name\",\"groupName\",\"unit\",\"frequency\",\"hidden\",\"every\",\"some\",\"none\",\"indicatorId_period\",\"description\",\"slug\",\"content\",\"date\",\"email\",\"password\",\"is\",\"isNot\",\"_relevance\",\"connectOrCreate\",\"upsert\",\"createMany\",\"set\",\"disconnect\",\"delete\",\"connect\",\"updateMany\",\"deleteMany\",\"increment\",\"decrement\",\"multiply\",\"divide\"]"), + graph: "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_AQAgjAEAAP4BADCNAQAAQwAQjgEAAP4BADCPAQIA0wEAIZQBQADWAQAhlQFAANYBACG7AQEA1AEAIcQBAQDUAQAhAwAAADIAIAMAAEIAMBIAAEMAIAMAAAAyACADAAAzADAEAAAvACAONwAA-gEAIIwBAAD4AQAwjQEAAE4AEI4BAAD4AQAwjwECAAAAAZQBQADnAQAhlQFAAOcBACGyAQEA5QEAIbQBAQDlAQAhuwEBAAAAAbwBAQDlAQAhvQEBAOUBACG-AQEA5QEAIb8BIAD5AQAhAQAAAEYAIAo2AAD9AQAgjAEAAPwBADCNAQAASAAQjgEAAPwBADCPAQIA5AEAIZQBQADnAQAhlQFAAOcBACGrAQEA5QEAIbkBAgDkAQAhugEIAO8BACECNgAAwgIAIMwBAADDAgAgCzYAAP0BACCMAQAA_AEAMI0BAABIABCOAQAA_AEAMI8BAgAAAAGUAUAA5wEAIZUBQADnAQAhqwEBAOUBACG5AQIA5AEAIboBCADvAQAhwwEAAPsBACADAAAASAAgAwAASQAwBAAASgAgAQAAAEgAIAEAAABGACAONwAA-gEAIIwBAAD4AQAwjQEAAE4AEI4BAAD4AQAwjwECAOQBACGUAUAA5wEAIZUBQADnAQAhsgEBAOUBACG0AQEA5QEAIbsBAQDlAQAhvAEBAOUBACG9AQEA5QEAIb4BAQDlAQAhvwEgAPkBACECNwAAwAIAIMwBAADBAgAgAwAAAE4AIAMAAE8AMAQAAEYAIAMAAABOACADAABPADAEAABGACADAAAATgAgAwAATwAwBAAARgAgCzcAAL8CACCPAQIAAAABlAFAAAAAAZUBQAAAAAGyAQEAAAABtAEBAAAAAbsBAQAAAAG8AQEAAAABvQEBAAAAAb4BAQAAAAG_ASAAAAABAQgAAFMAIAqPAQIAAAABlAFAAAAAAZUBQAAAAAGyAQEAAAABtAEBAAAAAbsBAQAAAAG8AQEAAAABvQEBAAAAAb4BAQAAAAG_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_AQAwBAAAuwEAIAMAAAC-AQAgAwAAvwEAMAQAALsBACAHjwECAAAAAZABAQAAAAGRAQEAAAABkgFAAAAAAZMBgAAAAAGUAUAAAAABlQFAAAAAAQEIAADDAQAgB48BAgAAAAGQAQEAAAABkQEBAAAAAZIBQAAAAAGTAYAAAAABlAFAAAAAAZUBQAAAAAEBCAAAxQEAMAePAQIAkAIAIZABAQCNAgAhkQEBAI4CACGSAUAAjwIAIZMBgAAAAAGUAUAAjwIAIZUBQACPAgAhAgAAALsBACAIAADHAQAgB48BAgCQAgAhkAEBAI0CACGRAQEAjgIAIZIBQACPAgAhkwGAAAAAAZQBQACPAgAhlQFAAI8CACECAAAAvgEAIAgAAMkBACADAAAAuwEAIA0AAMMBACAOAADHAQAgAQAAALsBACABAAAAvgEAIAcTAACIAgAgFAAAiQIAIBUAAIwCACAWAACLAgAgFwAAigIAIJEBAACHAgAgkwEAAIcCACAKjAEAANIBADCNAQAAzwEAEI4BAADSAQAwjwECANMBACGQAQEA1AEAIZEBAQDVAQAhkgFAANYBACGTAQAA1wEAIJQBQADWAQAhlQFAANYBACEDAAAAvgEAIAMAAM4BADASAADPAQAgAwAAAL4BACADAAC_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_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_ASAAAAABAgAAAEYAIA0AANcCACADAAAATgAgDQAA1wIAIA4AANsCACAMAAAATgAgCAAA2wIAII8BAgCQAgAhlAFAAI8CACGVAUAAjwIAIbIBAQCNAgAhtAEBAI0CACG7AQEAjQIAIbwBAQCNAgAhvQEBAI0CACG-AQEAjQIAIb8BIACxAgAhCo8BAgCQAgAhlAFAAI8CACGVAUAAjwIAIbIBAQCNAgAhtAEBAI0CACG7AQEAjQIAIbwBAQCNAgAhvQEBAI0CACG-AQEAjQIAIb8BIACxAgAhAAAFEwAEFAAFFQAGFgAHFwAIAAAAAAAFEwAEFAAFFQAGFgAHFwAIAAUTAAwUAA0VAA4WAA8XABAAAAAAAAUTAAwUAA0VAA4WAA8XABAABRMAFBQAFRUAFhYAFxcAGAAAAAAABRMAFBQAFRUAFhYAFxcAGAITABw3SxsBNgAaATdMAAUTAB4UAB8VACAWACEXACIAAAAAAAUTAB4UAB8VACAWACEXACIFEwAlFAAmFQAnFgAoFwApAAAAAAAFEwAlFAAmFQAnFgAoFwApAAUTAC0UAC4VAC8WADAXADEAAAAAAAUTAC0UAC4VAC8WADAXADEABRMANRQANhUANxYAOBcAOQAAAAAABRMANRQANhUANxYAOBcAOQAFEwA9FAA-FQA_FgBAFwBBAAAAAAAFEwA9FAA-FQA_FgBAFwBBAAUTAEUUAEYVAEcWAEgXAEkAAAAAAAUTAEUUAEYVAEcWAEgXAEkBAgECAwEFBgEGBwEHCAEJCgEKDAILDgEMEAIPEQEQEgEREwIYFgMZFwkaGQobGgocHQodHgoeHwofIQogIwIhJQoiJwIjKAokKQolKgImLQsnLhEoMBIpMRIqNBIrNRIsNhItOBIuOgIvPBIwPgIxPxIyQBIzQQI0RBM1RRk4Rxo5TRo6UBo7URo8Uho9VBo-VgI_WBpAWgJBWxpCXBpDXQJEYB1FYSNGYhtHYxtIZBtJZRtKZhtLaBtMagJNbBtObgJPbxtQcBtRcQJSdCRTdSpUdytVeCtWeytXfCtYfStZfytagQECW4MBK1yFAQJdhgErXocBK1-IAQJgiwEsYYwBMmKOATNjjwEzZJIBM2WTATNmlAEzZ5YBM2iYAQJpmgEzapwBAmudATNsngEzbZ8BAm6iATRvowE6cKUBO3GmATtyqQE7c6oBO3SrATt1rQE7dq8BAnexATt4swECebQBO3q1ATt7tgECfLkBPH26AUJ-vAFDf70BQ4ABwAFDgQHBAUOCAcIBQ4MBxAFDhAHGAQKFAcgBQ4YBygEChwHLAUOIAcwBQ4kBzQECigHQAUSLAdEBSg" } async function decodeBase64AsWasm(wasmBase64: string): Promise { @@ -238,6 +238,26 @@ export interface PrismaClient< */ get indicatorPoint(): Prisma.IndicatorPointDelegate; + /** + * `prisma.news`: Exposes CRUD operations for the **News** model. + * Example usage: + * ```ts + * // Fetch zero or more News + * const news = await prisma.news.findMany() + * ``` + */ + get news(): Prisma.NewsDelegate; + + /** + * `prisma.alert`: Exposes CRUD operations for the **Alert** model. + * Example usage: + * ```ts + * // Fetch zero or more Alerts + * const alerts = await prisma.alert.findMany() + * ``` + */ + get alert(): Prisma.AlertDelegate; + /** * `prisma.econ_SowInventory`: Exposes CRUD operations for the **Econ_SowInventory** model. * Example usage: diff --git a/generated/prisma/internal/prismaNamespace.ts b/generated/prisma/internal/prismaNamespace.ts index b6104d1..1d7164f 100644 --- a/generated/prisma/internal/prismaNamespace.ts +++ b/generated/prisma/internal/prismaNamespace.ts @@ -389,6 +389,8 @@ export const ModelName = { Strategy: 'Strategy', Indicator: 'Indicator', IndicatorPoint: 'IndicatorPoint', + News: 'News', + Alert: 'Alert', Econ_SowInventory: 'Econ_SowInventory', ScraperCache: 'ScraperCache' } as const @@ -406,7 +408,7 @@ export type TypeMap + fields: Prisma.NewsFieldRefs + operations: { + findUnique: { + args: Prisma.NewsFindUniqueArgs + result: runtime.Types.Utils.PayloadToResult | null + } + findUniqueOrThrow: { + args: Prisma.NewsFindUniqueOrThrowArgs + result: runtime.Types.Utils.PayloadToResult + } + findFirst: { + args: Prisma.NewsFindFirstArgs + result: runtime.Types.Utils.PayloadToResult | null + } + findFirstOrThrow: { + args: Prisma.NewsFindFirstOrThrowArgs + result: runtime.Types.Utils.PayloadToResult + } + findMany: { + args: Prisma.NewsFindManyArgs + result: runtime.Types.Utils.PayloadToResult[] + } + create: { + args: Prisma.NewsCreateArgs + result: runtime.Types.Utils.PayloadToResult + } + createMany: { + args: Prisma.NewsCreateManyArgs + result: BatchPayload + } + delete: { + args: Prisma.NewsDeleteArgs + result: runtime.Types.Utils.PayloadToResult + } + update: { + args: Prisma.NewsUpdateArgs + result: runtime.Types.Utils.PayloadToResult + } + deleteMany: { + args: Prisma.NewsDeleteManyArgs + result: BatchPayload + } + updateMany: { + args: Prisma.NewsUpdateManyArgs + result: BatchPayload + } + upsert: { + args: Prisma.NewsUpsertArgs + result: runtime.Types.Utils.PayloadToResult + } + aggregate: { + args: Prisma.NewsAggregateArgs + result: runtime.Types.Utils.Optional + } + groupBy: { + args: Prisma.NewsGroupByArgs + result: runtime.Types.Utils.Optional[] + } + count: { + args: Prisma.NewsCountArgs + result: runtime.Types.Utils.Optional | number + } + } + } + Alert: { + payload: Prisma.$AlertPayload + fields: Prisma.AlertFieldRefs + operations: { + findUnique: { + args: Prisma.AlertFindUniqueArgs + result: runtime.Types.Utils.PayloadToResult | null + } + findUniqueOrThrow: { + args: Prisma.AlertFindUniqueOrThrowArgs + result: runtime.Types.Utils.PayloadToResult + } + findFirst: { + args: Prisma.AlertFindFirstArgs + result: runtime.Types.Utils.PayloadToResult | null + } + findFirstOrThrow: { + args: Prisma.AlertFindFirstOrThrowArgs + result: runtime.Types.Utils.PayloadToResult + } + findMany: { + args: Prisma.AlertFindManyArgs + result: runtime.Types.Utils.PayloadToResult[] + } + create: { + args: Prisma.AlertCreateArgs + result: runtime.Types.Utils.PayloadToResult + } + createMany: { + args: Prisma.AlertCreateManyArgs + result: BatchPayload + } + delete: { + args: Prisma.AlertDeleteArgs + result: runtime.Types.Utils.PayloadToResult + } + update: { + args: Prisma.AlertUpdateArgs + result: runtime.Types.Utils.PayloadToResult + } + deleteMany: { + args: Prisma.AlertDeleteManyArgs + result: BatchPayload + } + updateMany: { + args: Prisma.AlertUpdateManyArgs + result: BatchPayload + } + upsert: { + args: Prisma.AlertUpsertArgs + result: runtime.Types.Utils.PayloadToResult + } + aggregate: { + args: Prisma.AlertAggregateArgs + result: runtime.Types.Utils.Optional + } + groupBy: { + args: Prisma.AlertGroupByArgs + result: runtime.Types.Utils.Optional[] + } + count: { + args: Prisma.AlertCountArgs + result: runtime.Types.Utils.Optional | number + } + } + } Econ_SowInventory: { payload: Prisma.$Econ_SowInventoryPayload fields: Prisma.Econ_SowInventoryFieldRefs @@ -976,6 +1110,36 @@ export const IndicatorPointScalarFieldEnum = { export type IndicatorPointScalarFieldEnum = (typeof IndicatorPointScalarFieldEnum)[keyof typeof IndicatorPointScalarFieldEnum] +export const NewsScalarFieldEnum = { + id: 'id', + title: 'title', + summary: 'summary', + source: 'source', + url: 'url', + publishedAt: 'publishedAt', + impactRank: 'impactRank', + createdAt: 'createdAt' +} as const + +export type NewsScalarFieldEnum = (typeof NewsScalarFieldEnum)[keyof typeof NewsScalarFieldEnum] + + +export const AlertScalarFieldEnum = { + id: 'id', + indicatorName: 'indicatorName', + period: 'period', + valueA: 'valueA', + valueB: 'valueB', + sourceA: 'sourceA', + sourceB: 'sourceB', + diff: 'diff', + diffRatio: 'diffRatio', + createdAt: 'createdAt' +} as const + +export type AlertScalarFieldEnum = (typeof AlertScalarFieldEnum)[keyof typeof AlertScalarFieldEnum] + + export const Econ_SowInventoryScalarFieldEnum = { id: 'id', month: 'month', @@ -1086,6 +1250,26 @@ export const IndicatorPointOrderByRelevanceFieldEnum = { export type IndicatorPointOrderByRelevanceFieldEnum = (typeof IndicatorPointOrderByRelevanceFieldEnum)[keyof typeof IndicatorPointOrderByRelevanceFieldEnum] +export const NewsOrderByRelevanceFieldEnum = { + title: 'title', + summary: 'summary', + source: 'source', + url: 'url' +} as const + +export type NewsOrderByRelevanceFieldEnum = (typeof NewsOrderByRelevanceFieldEnum)[keyof typeof NewsOrderByRelevanceFieldEnum] + + +export const AlertOrderByRelevanceFieldEnum = { + indicatorName: 'indicatorName', + period: 'period', + sourceA: 'sourceA', + sourceB: 'sourceB' +} as const + +export type AlertOrderByRelevanceFieldEnum = (typeof AlertOrderByRelevanceFieldEnum)[keyof typeof AlertOrderByRelevanceFieldEnum] + + export const Econ_SowInventoryOrderByRelevanceFieldEnum = { month: 'month' } as const @@ -1263,6 +1447,8 @@ export type GlobalOmitConfig = { strategy?: Prisma.StrategyOmit indicator?: Prisma.IndicatorOmit indicatorPoint?: Prisma.IndicatorPointOmit + news?: Prisma.NewsOmit + alert?: Prisma.AlertOmit econ_SowInventory?: Prisma.Econ_SowInventoryOmit scraperCache?: Prisma.ScraperCacheOmit } diff --git a/generated/prisma/internal/prismaNamespaceBrowser.ts b/generated/prisma/internal/prismaNamespaceBrowser.ts index 292b644..14263c9 100644 --- a/generated/prisma/internal/prismaNamespaceBrowser.ts +++ b/generated/prisma/internal/prismaNamespaceBrowser.ts @@ -56,6 +56,8 @@ export const ModelName = { Strategy: 'Strategy', Indicator: 'Indicator', IndicatorPoint: 'IndicatorPoint', + News: 'News', + Alert: 'Alert', Econ_SowInventory: 'Econ_SowInventory', ScraperCache: 'ScraperCache' } as const @@ -141,6 +143,36 @@ export const IndicatorPointScalarFieldEnum = { export type IndicatorPointScalarFieldEnum = (typeof IndicatorPointScalarFieldEnum)[keyof typeof IndicatorPointScalarFieldEnum] +export const NewsScalarFieldEnum = { + id: 'id', + title: 'title', + summary: 'summary', + source: 'source', + url: 'url', + publishedAt: 'publishedAt', + impactRank: 'impactRank', + createdAt: 'createdAt' +} as const + +export type NewsScalarFieldEnum = (typeof NewsScalarFieldEnum)[keyof typeof NewsScalarFieldEnum] + + +export const AlertScalarFieldEnum = { + id: 'id', + indicatorName: 'indicatorName', + period: 'period', + valueA: 'valueA', + valueB: 'valueB', + sourceA: 'sourceA', + sourceB: 'sourceB', + diff: 'diff', + diffRatio: 'diffRatio', + createdAt: 'createdAt' +} as const + +export type AlertScalarFieldEnum = (typeof AlertScalarFieldEnum)[keyof typeof AlertScalarFieldEnum] + + export const Econ_SowInventoryScalarFieldEnum = { id: 'id', month: 'month', @@ -251,6 +283,26 @@ export const IndicatorPointOrderByRelevanceFieldEnum = { export type IndicatorPointOrderByRelevanceFieldEnum = (typeof IndicatorPointOrderByRelevanceFieldEnum)[keyof typeof IndicatorPointOrderByRelevanceFieldEnum] +export const NewsOrderByRelevanceFieldEnum = { + title: 'title', + summary: 'summary', + source: 'source', + url: 'url' +} as const + +export type NewsOrderByRelevanceFieldEnum = (typeof NewsOrderByRelevanceFieldEnum)[keyof typeof NewsOrderByRelevanceFieldEnum] + + +export const AlertOrderByRelevanceFieldEnum = { + indicatorName: 'indicatorName', + period: 'period', + sourceA: 'sourceA', + sourceB: 'sourceB' +} as const + +export type AlertOrderByRelevanceFieldEnum = (typeof AlertOrderByRelevanceFieldEnum)[keyof typeof AlertOrderByRelevanceFieldEnum] + + export const Econ_SowInventoryOrderByRelevanceFieldEnum = { month: 'month' } as const diff --git a/generated/prisma/models.ts b/generated/prisma/models.ts index 9ee485c..0234ad0 100644 --- a/generated/prisma/models.ts +++ b/generated/prisma/models.ts @@ -13,6 +13,8 @@ export type * from './models/Article.ts' export type * from './models/Strategy.ts' export type * from './models/Indicator.ts' export type * from './models/IndicatorPoint.ts' +export type * from './models/News.ts' +export type * from './models/Alert.ts' export type * from './models/Econ_SowInventory.ts' export type * from './models/ScraperCache.ts' export type * from './commonInputTypes.ts' \ No newline at end of file diff --git a/generated/prisma/models/Alert.ts b/generated/prisma/models/Alert.ts new file mode 100644 index 0000000..2d2db2a --- /dev/null +++ b/generated/prisma/models/Alert.ts @@ -0,0 +1,1238 @@ + +/* !!! This is code generated by Prisma. Do not edit directly. !!! */ +/* eslint-disable */ +// biome-ignore-all lint: generated file +// @ts-nocheck +/* + * This file exports the `Alert` model and its related types. + * + * 🟢 You can import this file directly. + */ +import type * as runtime from "@prisma/client/runtime/client" +import type * as $Enums from "../enums.ts" +import type * as Prisma from "../internal/prismaNamespace.ts" + +/** + * Model Alert + * + */ +export type AlertModel = runtime.Types.Result.DefaultSelection + +export type AggregateAlert = { + _count: AlertCountAggregateOutputType | null + _avg: AlertAvgAggregateOutputType | null + _sum: AlertSumAggregateOutputType | null + _min: AlertMinAggregateOutputType | null + _max: AlertMaxAggregateOutputType | null +} + +export type AlertAvgAggregateOutputType = { + id: number | null + valueA: number | null + valueB: number | null + diff: number | null + diffRatio: number | null +} + +export type AlertSumAggregateOutputType = { + id: number | null + valueA: number | null + valueB: number | null + diff: number | null + diffRatio: number | null +} + +export type AlertMinAggregateOutputType = { + id: number | null + indicatorName: string | null + period: string | null + valueA: number | null + valueB: number | null + sourceA: string | null + sourceB: string | null + diff: number | null + diffRatio: number | null + createdAt: Date | null +} + +export type AlertMaxAggregateOutputType = { + id: number | null + indicatorName: string | null + period: string | null + valueA: number | null + valueB: number | null + sourceA: string | null + sourceB: string | null + diff: number | null + diffRatio: number | null + createdAt: Date | null +} + +export type AlertCountAggregateOutputType = { + id: number + indicatorName: number + period: number + valueA: number + valueB: number + sourceA: number + sourceB: number + diff: number + diffRatio: number + createdAt: number + _all: number +} + + +export type AlertAvgAggregateInputType = { + id?: true + valueA?: true + valueB?: true + diff?: true + diffRatio?: true +} + +export type AlertSumAggregateInputType = { + id?: true + valueA?: true + valueB?: true + diff?: true + diffRatio?: true +} + +export type AlertMinAggregateInputType = { + id?: true + indicatorName?: true + period?: true + valueA?: true + valueB?: true + sourceA?: true + sourceB?: true + diff?: true + diffRatio?: true + createdAt?: true +} + +export type AlertMaxAggregateInputType = { + id?: true + indicatorName?: true + period?: true + valueA?: true + valueB?: true + sourceA?: true + sourceB?: true + diff?: true + diffRatio?: true + createdAt?: true +} + +export type AlertCountAggregateInputType = { + id?: true + indicatorName?: true + period?: true + valueA?: true + valueB?: true + sourceA?: true + sourceB?: true + diff?: true + diffRatio?: true + createdAt?: true + _all?: true +} + +export type AlertAggregateArgs = { + /** + * Filter which Alert to aggregate. + */ + where?: Prisma.AlertWhereInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/sorting Sorting Docs} + * + * Determine the order of Alerts to fetch. + */ + orderBy?: Prisma.AlertOrderByWithRelationInput | Prisma.AlertOrderByWithRelationInput[] + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination#cursor-based-pagination Cursor Docs} + * + * Sets the start position + */ + cursor?: Prisma.AlertWhereUniqueInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Take `±n` Alerts from the position of the cursor. + */ + take?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Skip the first `n` Alerts. + */ + skip?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Count returned Alerts + **/ + _count?: true | AlertCountAggregateInputType + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Select which fields to average + **/ + _avg?: AlertAvgAggregateInputType + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Select which fields to sum + **/ + _sum?: AlertSumAggregateInputType + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Select which fields to find the minimum value + **/ + _min?: AlertMinAggregateInputType + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Select which fields to find the maximum value + **/ + _max?: AlertMaxAggregateInputType +} + +export type GetAlertAggregateType = { + [P in keyof T & keyof AggregateAlert]: P extends '_count' | 'count' + ? T[P] extends true + ? number + : Prisma.GetScalarType + : Prisma.GetScalarType +} + + + + +export type AlertGroupByArgs = { + where?: Prisma.AlertWhereInput + orderBy?: Prisma.AlertOrderByWithAggregationInput | Prisma.AlertOrderByWithAggregationInput[] + by: Prisma.AlertScalarFieldEnum[] | Prisma.AlertScalarFieldEnum + having?: Prisma.AlertScalarWhereWithAggregatesInput + take?: number + skip?: number + _count?: AlertCountAggregateInputType | true + _avg?: AlertAvgAggregateInputType + _sum?: AlertSumAggregateInputType + _min?: AlertMinAggregateInputType + _max?: AlertMaxAggregateInputType +} + +export type AlertGroupByOutputType = { + id: number + indicatorName: string + period: string + valueA: number + valueB: number + sourceA: string + sourceB: string + diff: number + diffRatio: number + createdAt: Date + _count: AlertCountAggregateOutputType | null + _avg: AlertAvgAggregateOutputType | null + _sum: AlertSumAggregateOutputType | null + _min: AlertMinAggregateOutputType | null + _max: AlertMaxAggregateOutputType | null +} + +export type GetAlertGroupByPayload = Prisma.PrismaPromise< + Array< + Prisma.PickEnumerable & + { + [P in ((keyof T) & (keyof AlertGroupByOutputType))]: P extends '_count' + ? T[P] extends boolean + ? number + : Prisma.GetScalarType + : Prisma.GetScalarType + } + > + > + + + +export type AlertWhereInput = { + AND?: Prisma.AlertWhereInput | Prisma.AlertWhereInput[] + OR?: Prisma.AlertWhereInput[] + NOT?: Prisma.AlertWhereInput | Prisma.AlertWhereInput[] + id?: Prisma.IntFilter<"Alert"> | number + indicatorName?: Prisma.StringFilter<"Alert"> | string + period?: Prisma.StringFilter<"Alert"> | string + valueA?: Prisma.FloatFilter<"Alert"> | number + valueB?: Prisma.FloatFilter<"Alert"> | number + sourceA?: Prisma.StringFilter<"Alert"> | string + sourceB?: Prisma.StringFilter<"Alert"> | string + diff?: Prisma.FloatFilter<"Alert"> | number + diffRatio?: Prisma.FloatFilter<"Alert"> | number + createdAt?: Prisma.DateTimeFilter<"Alert"> | Date | string +} + +export type AlertOrderByWithRelationInput = { + id?: Prisma.SortOrder + indicatorName?: Prisma.SortOrder + period?: Prisma.SortOrder + valueA?: Prisma.SortOrder + valueB?: Prisma.SortOrder + sourceA?: Prisma.SortOrder + sourceB?: Prisma.SortOrder + diff?: Prisma.SortOrder + diffRatio?: Prisma.SortOrder + createdAt?: Prisma.SortOrder + _relevance?: Prisma.AlertOrderByRelevanceInput +} + +export type AlertWhereUniqueInput = Prisma.AtLeast<{ + id?: number + AND?: Prisma.AlertWhereInput | Prisma.AlertWhereInput[] + OR?: Prisma.AlertWhereInput[] + NOT?: Prisma.AlertWhereInput | Prisma.AlertWhereInput[] + indicatorName?: Prisma.StringFilter<"Alert"> | string + period?: Prisma.StringFilter<"Alert"> | string + valueA?: Prisma.FloatFilter<"Alert"> | number + valueB?: Prisma.FloatFilter<"Alert"> | number + sourceA?: Prisma.StringFilter<"Alert"> | string + sourceB?: Prisma.StringFilter<"Alert"> | string + diff?: Prisma.FloatFilter<"Alert"> | number + diffRatio?: Prisma.FloatFilter<"Alert"> | number + createdAt?: Prisma.DateTimeFilter<"Alert"> | Date | string +}, "id"> + +export type AlertOrderByWithAggregationInput = { + id?: Prisma.SortOrder + indicatorName?: Prisma.SortOrder + period?: Prisma.SortOrder + valueA?: Prisma.SortOrder + valueB?: Prisma.SortOrder + sourceA?: Prisma.SortOrder + sourceB?: Prisma.SortOrder + diff?: Prisma.SortOrder + diffRatio?: Prisma.SortOrder + createdAt?: Prisma.SortOrder + _count?: Prisma.AlertCountOrderByAggregateInput + _avg?: Prisma.AlertAvgOrderByAggregateInput + _max?: Prisma.AlertMaxOrderByAggregateInput + _min?: Prisma.AlertMinOrderByAggregateInput + _sum?: Prisma.AlertSumOrderByAggregateInput +} + +export type AlertScalarWhereWithAggregatesInput = { + AND?: Prisma.AlertScalarWhereWithAggregatesInput | Prisma.AlertScalarWhereWithAggregatesInput[] + OR?: Prisma.AlertScalarWhereWithAggregatesInput[] + NOT?: Prisma.AlertScalarWhereWithAggregatesInput | Prisma.AlertScalarWhereWithAggregatesInput[] + id?: Prisma.IntWithAggregatesFilter<"Alert"> | number + indicatorName?: Prisma.StringWithAggregatesFilter<"Alert"> | string + period?: Prisma.StringWithAggregatesFilter<"Alert"> | string + valueA?: Prisma.FloatWithAggregatesFilter<"Alert"> | number + valueB?: Prisma.FloatWithAggregatesFilter<"Alert"> | number + sourceA?: Prisma.StringWithAggregatesFilter<"Alert"> | string + sourceB?: Prisma.StringWithAggregatesFilter<"Alert"> | string + diff?: Prisma.FloatWithAggregatesFilter<"Alert"> | number + diffRatio?: Prisma.FloatWithAggregatesFilter<"Alert"> | number + createdAt?: Prisma.DateTimeWithAggregatesFilter<"Alert"> | Date | string +} + +export type AlertCreateInput = { + indicatorName: string + period: string + valueA: number + valueB: number + sourceA: string + sourceB: string + diff: number + diffRatio: number + createdAt?: Date | string +} + +export type AlertUncheckedCreateInput = { + id?: number + indicatorName: string + period: string + valueA: number + valueB: number + sourceA: string + sourceB: string + diff: number + diffRatio: number + createdAt?: Date | string +} + +export type AlertUpdateInput = { + indicatorName?: Prisma.StringFieldUpdateOperationsInput | string + period?: Prisma.StringFieldUpdateOperationsInput | string + valueA?: Prisma.FloatFieldUpdateOperationsInput | number + valueB?: Prisma.FloatFieldUpdateOperationsInput | number + sourceA?: Prisma.StringFieldUpdateOperationsInput | string + sourceB?: Prisma.StringFieldUpdateOperationsInput | string + diff?: Prisma.FloatFieldUpdateOperationsInput | number + diffRatio?: Prisma.FloatFieldUpdateOperationsInput | number + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string +} + +export type AlertUncheckedUpdateInput = { + id?: Prisma.IntFieldUpdateOperationsInput | number + indicatorName?: Prisma.StringFieldUpdateOperationsInput | string + period?: Prisma.StringFieldUpdateOperationsInput | string + valueA?: Prisma.FloatFieldUpdateOperationsInput | number + valueB?: Prisma.FloatFieldUpdateOperationsInput | number + sourceA?: Prisma.StringFieldUpdateOperationsInput | string + sourceB?: Prisma.StringFieldUpdateOperationsInput | string + diff?: Prisma.FloatFieldUpdateOperationsInput | number + diffRatio?: Prisma.FloatFieldUpdateOperationsInput | number + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string +} + +export type AlertCreateManyInput = { + id?: number + indicatorName: string + period: string + valueA: number + valueB: number + sourceA: string + sourceB: string + diff: number + diffRatio: number + createdAt?: Date | string +} + +export type AlertUpdateManyMutationInput = { + indicatorName?: Prisma.StringFieldUpdateOperationsInput | string + period?: Prisma.StringFieldUpdateOperationsInput | string + valueA?: Prisma.FloatFieldUpdateOperationsInput | number + valueB?: Prisma.FloatFieldUpdateOperationsInput | number + sourceA?: Prisma.StringFieldUpdateOperationsInput | string + sourceB?: Prisma.StringFieldUpdateOperationsInput | string + diff?: Prisma.FloatFieldUpdateOperationsInput | number + diffRatio?: Prisma.FloatFieldUpdateOperationsInput | number + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string +} + +export type AlertUncheckedUpdateManyInput = { + id?: Prisma.IntFieldUpdateOperationsInput | number + indicatorName?: Prisma.StringFieldUpdateOperationsInput | string + period?: Prisma.StringFieldUpdateOperationsInput | string + valueA?: Prisma.FloatFieldUpdateOperationsInput | number + valueB?: Prisma.FloatFieldUpdateOperationsInput | number + sourceA?: Prisma.StringFieldUpdateOperationsInput | string + sourceB?: Prisma.StringFieldUpdateOperationsInput | string + diff?: Prisma.FloatFieldUpdateOperationsInput | number + diffRatio?: Prisma.FloatFieldUpdateOperationsInput | number + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string +} + +export type AlertOrderByRelevanceInput = { + fields: Prisma.AlertOrderByRelevanceFieldEnum | Prisma.AlertOrderByRelevanceFieldEnum[] + sort: Prisma.SortOrder + search: string +} + +export type AlertCountOrderByAggregateInput = { + id?: Prisma.SortOrder + indicatorName?: Prisma.SortOrder + period?: Prisma.SortOrder + valueA?: Prisma.SortOrder + valueB?: Prisma.SortOrder + sourceA?: Prisma.SortOrder + sourceB?: Prisma.SortOrder + diff?: Prisma.SortOrder + diffRatio?: Prisma.SortOrder + createdAt?: Prisma.SortOrder +} + +export type AlertAvgOrderByAggregateInput = { + id?: Prisma.SortOrder + valueA?: Prisma.SortOrder + valueB?: Prisma.SortOrder + diff?: Prisma.SortOrder + diffRatio?: Prisma.SortOrder +} + +export type AlertMaxOrderByAggregateInput = { + id?: Prisma.SortOrder + indicatorName?: Prisma.SortOrder + period?: Prisma.SortOrder + valueA?: Prisma.SortOrder + valueB?: Prisma.SortOrder + sourceA?: Prisma.SortOrder + sourceB?: Prisma.SortOrder + diff?: Prisma.SortOrder + diffRatio?: Prisma.SortOrder + createdAt?: Prisma.SortOrder +} + +export type AlertMinOrderByAggregateInput = { + id?: Prisma.SortOrder + indicatorName?: Prisma.SortOrder + period?: Prisma.SortOrder + valueA?: Prisma.SortOrder + valueB?: Prisma.SortOrder + sourceA?: Prisma.SortOrder + sourceB?: Prisma.SortOrder + diff?: Prisma.SortOrder + diffRatio?: Prisma.SortOrder + createdAt?: Prisma.SortOrder +} + +export type AlertSumOrderByAggregateInput = { + id?: Prisma.SortOrder + valueA?: Prisma.SortOrder + valueB?: Prisma.SortOrder + diff?: Prisma.SortOrder + diffRatio?: Prisma.SortOrder +} + + + +export type AlertSelect = runtime.Types.Extensions.GetSelect<{ + id?: boolean + indicatorName?: boolean + period?: boolean + valueA?: boolean + valueB?: boolean + sourceA?: boolean + sourceB?: boolean + diff?: boolean + diffRatio?: boolean + createdAt?: boolean +}, ExtArgs["result"]["alert"]> + + + +export type AlertSelectScalar = { + id?: boolean + indicatorName?: boolean + period?: boolean + valueA?: boolean + valueB?: boolean + sourceA?: boolean + sourceB?: boolean + diff?: boolean + diffRatio?: boolean + createdAt?: boolean +} + +export type AlertOmit = runtime.Types.Extensions.GetOmit<"id" | "indicatorName" | "period" | "valueA" | "valueB" | "sourceA" | "sourceB" | "diff" | "diffRatio" | "createdAt", ExtArgs["result"]["alert"]> + +export type $AlertPayload = { + name: "Alert" + objects: {} + scalars: runtime.Types.Extensions.GetPayloadResult<{ + id: number + indicatorName: string + period: string + valueA: number + valueB: number + sourceA: string + sourceB: string + diff: number + diffRatio: number + createdAt: Date + }, ExtArgs["result"]["alert"]> + composites: {} +} + +export type AlertGetPayload = runtime.Types.Result.GetResult + +export type AlertCountArgs = + Omit & { + select?: AlertCountAggregateInputType | true + } + +export interface AlertDelegate { + [K: symbol]: { types: Prisma.TypeMap['model']['Alert'], meta: { name: 'Alert' } } + /** + * Find zero or one Alert that matches the filter. + * @param {AlertFindUniqueArgs} args - Arguments to find a Alert + * @example + * // Get one Alert + * const alert = await prisma.alert.findUnique({ + * where: { + * // ... provide filter here + * } + * }) + */ + findUnique(args: Prisma.SelectSubset>): Prisma.Prisma__AlertClient, T, "findUnique", GlobalOmitOptions> | null, null, ExtArgs, GlobalOmitOptions> + + /** + * Find one Alert that matches the filter or throw an error with `error.code='P2025'` + * if no matches were found. + * @param {AlertFindUniqueOrThrowArgs} args - Arguments to find a Alert + * @example + * // Get one Alert + * const alert = await prisma.alert.findUniqueOrThrow({ + * where: { + * // ... provide filter here + * } + * }) + */ + findUniqueOrThrow(args: Prisma.SelectSubset>): Prisma.Prisma__AlertClient, T, "findUniqueOrThrow", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + /** + * Find the first Alert that matches the filter. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {AlertFindFirstArgs} args - Arguments to find a Alert + * @example + * // Get one Alert + * const alert = await prisma.alert.findFirst({ + * where: { + * // ... provide filter here + * } + * }) + */ + findFirst(args?: Prisma.SelectSubset>): Prisma.Prisma__AlertClient, T, "findFirst", GlobalOmitOptions> | null, null, ExtArgs, GlobalOmitOptions> + + /** + * Find the first Alert that matches the filter or + * throw `PrismaKnownClientError` with `P2025` code if no matches were found. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {AlertFindFirstOrThrowArgs} args - Arguments to find a Alert + * @example + * // Get one Alert + * const alert = await prisma.alert.findFirstOrThrow({ + * where: { + * // ... provide filter here + * } + * }) + */ + findFirstOrThrow(args?: Prisma.SelectSubset>): Prisma.Prisma__AlertClient, T, "findFirstOrThrow", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + /** + * Find zero or more Alerts that matches the filter. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {AlertFindManyArgs} args - Arguments to filter and select certain fields only. + * @example + * // Get all Alerts + * const alerts = await prisma.alert.findMany() + * + * // Get first 10 Alerts + * const alerts = await prisma.alert.findMany({ take: 10 }) + * + * // Only select the `id` + * const alertWithIdOnly = await prisma.alert.findMany({ select: { id: true } }) + * + */ + findMany(args?: Prisma.SelectSubset>): Prisma.PrismaPromise, T, "findMany", GlobalOmitOptions>> + + /** + * Create a Alert. + * @param {AlertCreateArgs} args - Arguments to create a Alert. + * @example + * // Create one Alert + * const Alert = await prisma.alert.create({ + * data: { + * // ... data to create a Alert + * } + * }) + * + */ + create(args: Prisma.SelectSubset>): Prisma.Prisma__AlertClient, T, "create", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + /** + * Create many Alerts. + * @param {AlertCreateManyArgs} args - Arguments to create many Alerts. + * @example + * // Create many Alerts + * const alert = await prisma.alert.createMany({ + * data: [ + * // ... provide data here + * ] + * }) + * + */ + createMany(args?: Prisma.SelectSubset>): Prisma.PrismaPromise + + /** + * Delete a Alert. + * @param {AlertDeleteArgs} args - Arguments to delete one Alert. + * @example + * // Delete one Alert + * const Alert = await prisma.alert.delete({ + * where: { + * // ... filter to delete one Alert + * } + * }) + * + */ + delete(args: Prisma.SelectSubset>): Prisma.Prisma__AlertClient, T, "delete", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + /** + * Update one Alert. + * @param {AlertUpdateArgs} args - Arguments to update one Alert. + * @example + * // Update one Alert + * const alert = await prisma.alert.update({ + * where: { + * // ... provide filter here + * }, + * data: { + * // ... provide data here + * } + * }) + * + */ + update(args: Prisma.SelectSubset>): Prisma.Prisma__AlertClient, T, "update", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + /** + * Delete zero or more Alerts. + * @param {AlertDeleteManyArgs} args - Arguments to filter Alerts to delete. + * @example + * // Delete a few Alerts + * const { count } = await prisma.alert.deleteMany({ + * where: { + * // ... provide filter here + * } + * }) + * + */ + deleteMany(args?: Prisma.SelectSubset>): Prisma.PrismaPromise + + /** + * Update zero or more Alerts. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {AlertUpdateManyArgs} args - Arguments to update one or more rows. + * @example + * // Update many Alerts + * const alert = await prisma.alert.updateMany({ + * where: { + * // ... provide filter here + * }, + * data: { + * // ... provide data here + * } + * }) + * + */ + updateMany(args: Prisma.SelectSubset>): Prisma.PrismaPromise + + /** + * Create or update one Alert. + * @param {AlertUpsertArgs} args - Arguments to update or create a Alert. + * @example + * // Update or create a Alert + * const alert = await prisma.alert.upsert({ + * create: { + * // ... data to create a Alert + * }, + * update: { + * // ... in case it already exists, update + * }, + * where: { + * // ... the filter for the Alert we want to update + * } + * }) + */ + upsert(args: Prisma.SelectSubset>): Prisma.Prisma__AlertClient, T, "upsert", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + + /** + * Count the number of Alerts. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {AlertCountArgs} args - Arguments to filter Alerts to count. + * @example + * // Count the number of Alerts + * const count = await prisma.alert.count({ + * where: { + * // ... the filter for the Alerts we want to count + * } + * }) + **/ + count( + args?: Prisma.Subset, + ): Prisma.PrismaPromise< + T extends runtime.Types.Utils.Record<'select', any> + ? T['select'] extends true + ? number + : Prisma.GetScalarType + : number + > + + /** + * Allows you to perform aggregations operations on a Alert. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {AlertAggregateArgs} args - Select which aggregations you would like to apply and on what fields. + * @example + * // Ordered by age ascending + * // Where email contains prisma.io + * // Limited to the 10 users + * const aggregations = await prisma.user.aggregate({ + * _avg: { + * age: true, + * }, + * where: { + * email: { + * contains: "prisma.io", + * }, + * }, + * orderBy: { + * age: "asc", + * }, + * take: 10, + * }) + **/ + aggregate(args: Prisma.Subset): Prisma.PrismaPromise> + + /** + * Group by Alert. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {AlertGroupByArgs} args - Group by arguments. + * @example + * // Group by city, order by createdAt, get count + * const result = await prisma.user.groupBy({ + * by: ['city', 'createdAt'], + * orderBy: { + * createdAt: true + * }, + * _count: { + * _all: true + * }, + * }) + * + **/ + groupBy< + T extends AlertGroupByArgs, + HasSelectOrTake extends Prisma.Or< + Prisma.Extends<'skip', Prisma.Keys>, + Prisma.Extends<'take', Prisma.Keys> + >, + OrderByArg extends Prisma.True extends HasSelectOrTake + ? { orderBy: AlertGroupByArgs['orderBy'] } + : { orderBy?: AlertGroupByArgs['orderBy'] }, + OrderFields extends Prisma.ExcludeUnderscoreKeys>>, + ByFields extends Prisma.MaybeTupleToUnion, + ByValid extends Prisma.Has, + HavingFields extends Prisma.GetHavingFields, + HavingValid extends Prisma.Has, + ByEmpty extends T['by'] extends never[] ? Prisma.True : Prisma.False, + InputErrors extends ByEmpty extends Prisma.True + ? `Error: "by" must not be empty.` + : HavingValid extends Prisma.False + ? { + [P in HavingFields]: P extends ByFields + ? never + : P extends string + ? `Error: Field "${P}" used in "having" needs to be provided in "by".` + : [ + Error, + 'Field ', + P, + ` in "having" needs to be provided in "by"`, + ] + }[HavingFields] + : 'take' extends Prisma.Keys + ? 'orderBy' extends Prisma.Keys + ? ByValid extends Prisma.True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + : 'Error: If you provide "take", you also need to provide "orderBy"' + : 'skip' extends Prisma.Keys + ? 'orderBy' extends Prisma.Keys + ? ByValid extends Prisma.True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + : 'Error: If you provide "skip", you also need to provide "orderBy"' + : ByValid extends Prisma.True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + >(args: Prisma.SubsetIntersection & InputErrors): {} extends InputErrors ? GetAlertGroupByPayload : Prisma.PrismaPromise +/** + * Fields of the Alert model + */ +readonly fields: AlertFieldRefs; +} + +/** + * The delegate class that acts as a "Promise-like" for Alert. + * Why is this prefixed with `Prisma__`? + * Because we want to prevent naming conflicts as mentioned in + * https://github.com/prisma/prisma-client-js/issues/707 + */ +export interface Prisma__AlertClient extends Prisma.PrismaPromise { + readonly [Symbol.toStringTag]: "PrismaPromise" + /** + * Attaches callbacks for the resolution and/or rejection of the Promise. + * @param onfulfilled The callback to execute when the Promise is resolved. + * @param onrejected The callback to execute when the Promise is rejected. + * @returns A Promise for the completion of which ever callback is executed. + */ + then(onfulfilled?: ((value: T) => TResult1 | PromiseLike) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike) | undefined | null): runtime.Types.Utils.JsPromise + /** + * Attaches a callback for only the rejection of the Promise. + * @param onrejected The callback to execute when the Promise is rejected. + * @returns A Promise for the completion of the callback. + */ + catch(onrejected?: ((reason: any) => TResult | PromiseLike) | undefined | null): runtime.Types.Utils.JsPromise + /** + * Attaches a callback that is invoked when the Promise is settled (fulfilled or rejected). The + * resolved value cannot be modified from the callback. + * @param onfinally The callback to execute when the Promise is settled (fulfilled or rejected). + * @returns A Promise for the completion of the callback. + */ + finally(onfinally?: (() => void) | undefined | null): runtime.Types.Utils.JsPromise +} + + + + +/** + * Fields of the Alert model + */ +export interface AlertFieldRefs { + readonly id: Prisma.FieldRef<"Alert", 'Int'> + readonly indicatorName: Prisma.FieldRef<"Alert", 'String'> + readonly period: Prisma.FieldRef<"Alert", 'String'> + readonly valueA: Prisma.FieldRef<"Alert", 'Float'> + readonly valueB: Prisma.FieldRef<"Alert", 'Float'> + readonly sourceA: Prisma.FieldRef<"Alert", 'String'> + readonly sourceB: Prisma.FieldRef<"Alert", 'String'> + readonly diff: Prisma.FieldRef<"Alert", 'Float'> + readonly diffRatio: Prisma.FieldRef<"Alert", 'Float'> + readonly createdAt: Prisma.FieldRef<"Alert", 'DateTime'> +} + + +// Custom InputTypes +/** + * Alert findUnique + */ +export type AlertFindUniqueArgs = { + /** + * Select specific fields to fetch from the Alert + */ + select?: Prisma.AlertSelect | null + /** + * Omit specific fields from the Alert + */ + omit?: Prisma.AlertOmit | null + /** + * Filter, which Alert to fetch. + */ + where: Prisma.AlertWhereUniqueInput +} + +/** + * Alert findUniqueOrThrow + */ +export type AlertFindUniqueOrThrowArgs = { + /** + * Select specific fields to fetch from the Alert + */ + select?: Prisma.AlertSelect | null + /** + * Omit specific fields from the Alert + */ + omit?: Prisma.AlertOmit | null + /** + * Filter, which Alert to fetch. + */ + where: Prisma.AlertWhereUniqueInput +} + +/** + * Alert findFirst + */ +export type AlertFindFirstArgs = { + /** + * Select specific fields to fetch from the Alert + */ + select?: Prisma.AlertSelect | null + /** + * Omit specific fields from the Alert + */ + omit?: Prisma.AlertOmit | null + /** + * Filter, which Alert to fetch. + */ + where?: Prisma.AlertWhereInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/sorting Sorting Docs} + * + * Determine the order of Alerts to fetch. + */ + orderBy?: Prisma.AlertOrderByWithRelationInput | Prisma.AlertOrderByWithRelationInput[] + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination#cursor-based-pagination Cursor Docs} + * + * Sets the position for searching for Alerts. + */ + cursor?: Prisma.AlertWhereUniqueInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Take `±n` Alerts from the position of the cursor. + */ + take?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Skip the first `n` Alerts. + */ + skip?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/distinct Distinct Docs} + * + * Filter by unique combinations of Alerts. + */ + distinct?: Prisma.AlertScalarFieldEnum | Prisma.AlertScalarFieldEnum[] +} + +/** + * Alert findFirstOrThrow + */ +export type AlertFindFirstOrThrowArgs = { + /** + * Select specific fields to fetch from the Alert + */ + select?: Prisma.AlertSelect | null + /** + * Omit specific fields from the Alert + */ + omit?: Prisma.AlertOmit | null + /** + * Filter, which Alert to fetch. + */ + where?: Prisma.AlertWhereInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/sorting Sorting Docs} + * + * Determine the order of Alerts to fetch. + */ + orderBy?: Prisma.AlertOrderByWithRelationInput | Prisma.AlertOrderByWithRelationInput[] + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination#cursor-based-pagination Cursor Docs} + * + * Sets the position for searching for Alerts. + */ + cursor?: Prisma.AlertWhereUniqueInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Take `±n` Alerts from the position of the cursor. + */ + take?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Skip the first `n` Alerts. + */ + skip?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/distinct Distinct Docs} + * + * Filter by unique combinations of Alerts. + */ + distinct?: Prisma.AlertScalarFieldEnum | Prisma.AlertScalarFieldEnum[] +} + +/** + * Alert findMany + */ +export type AlertFindManyArgs = { + /** + * Select specific fields to fetch from the Alert + */ + select?: Prisma.AlertSelect | null + /** + * Omit specific fields from the Alert + */ + omit?: Prisma.AlertOmit | null + /** + * Filter, which Alerts to fetch. + */ + where?: Prisma.AlertWhereInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/sorting Sorting Docs} + * + * Determine the order of Alerts to fetch. + */ + orderBy?: Prisma.AlertOrderByWithRelationInput | Prisma.AlertOrderByWithRelationInput[] + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination#cursor-based-pagination Cursor Docs} + * + * Sets the position for listing Alerts. + */ + cursor?: Prisma.AlertWhereUniqueInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Take `±n` Alerts from the position of the cursor. + */ + take?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Skip the first `n` Alerts. + */ + skip?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/distinct Distinct Docs} + * + * Filter by unique combinations of Alerts. + */ + distinct?: Prisma.AlertScalarFieldEnum | Prisma.AlertScalarFieldEnum[] +} + +/** + * Alert create + */ +export type AlertCreateArgs = { + /** + * Select specific fields to fetch from the Alert + */ + select?: Prisma.AlertSelect | null + /** + * Omit specific fields from the Alert + */ + omit?: Prisma.AlertOmit | null + /** + * The data needed to create a Alert. + */ + data: Prisma.XOR +} + +/** + * Alert createMany + */ +export type AlertCreateManyArgs = { + /** + * The data used to create many Alerts. + */ + data: Prisma.AlertCreateManyInput | Prisma.AlertCreateManyInput[] + skipDuplicates?: boolean +} + +/** + * Alert update + */ +export type AlertUpdateArgs = { + /** + * Select specific fields to fetch from the Alert + */ + select?: Prisma.AlertSelect | null + /** + * Omit specific fields from the Alert + */ + omit?: Prisma.AlertOmit | null + /** + * The data needed to update a Alert. + */ + data: Prisma.XOR + /** + * Choose, which Alert to update. + */ + where: Prisma.AlertWhereUniqueInput +} + +/** + * Alert updateMany + */ +export type AlertUpdateManyArgs = { + /** + * The data used to update Alerts. + */ + data: Prisma.XOR + /** + * Filter which Alerts to update + */ + where?: Prisma.AlertWhereInput + /** + * Limit how many Alerts to update. + */ + limit?: number +} + +/** + * Alert upsert + */ +export type AlertUpsertArgs = { + /** + * Select specific fields to fetch from the Alert + */ + select?: Prisma.AlertSelect | null + /** + * Omit specific fields from the Alert + */ + omit?: Prisma.AlertOmit | null + /** + * The filter to search for the Alert to update in case it exists. + */ + where: Prisma.AlertWhereUniqueInput + /** + * In case the Alert found by the `where` argument doesn't exist, create a new Alert with this data. + */ + create: Prisma.XOR + /** + * In case the Alert was found with the provided `where` argument, update it with this data. + */ + update: Prisma.XOR +} + +/** + * Alert delete + */ +export type AlertDeleteArgs = { + /** + * Select specific fields to fetch from the Alert + */ + select?: Prisma.AlertSelect | null + /** + * Omit specific fields from the Alert + */ + omit?: Prisma.AlertOmit | null + /** + * Filter which Alert to delete. + */ + where: Prisma.AlertWhereUniqueInput +} + +/** + * Alert deleteMany + */ +export type AlertDeleteManyArgs = { + /** + * Filter which Alerts to delete + */ + where?: Prisma.AlertWhereInput + /** + * Limit how many Alerts to delete. + */ + limit?: number +} + +/** + * Alert without action + */ +export type AlertDefaultArgs = { + /** + * Select specific fields to fetch from the Alert + */ + select?: Prisma.AlertSelect | null + /** + * Omit specific fields from the Alert + */ + omit?: Prisma.AlertOmit | null +} diff --git a/generated/prisma/models/News.ts b/generated/prisma/models/News.ts new file mode 100644 index 0000000..00eb288 --- /dev/null +++ b/generated/prisma/models/News.ts @@ -0,0 +1,1174 @@ + +/* !!! This is code generated by Prisma. Do not edit directly. !!! */ +/* eslint-disable */ +// biome-ignore-all lint: generated file +// @ts-nocheck +/* + * This file exports the `News` model and its related types. + * + * 🟢 You can import this file directly. + */ +import type * as runtime from "@prisma/client/runtime/client" +import type * as $Enums from "../enums.ts" +import type * as Prisma from "../internal/prismaNamespace.ts" + +/** + * Model News + * + */ +export type NewsModel = runtime.Types.Result.DefaultSelection + +export type AggregateNews = { + _count: NewsCountAggregateOutputType | null + _avg: NewsAvgAggregateOutputType | null + _sum: NewsSumAggregateOutputType | null + _min: NewsMinAggregateOutputType | null + _max: NewsMaxAggregateOutputType | null +} + +export type NewsAvgAggregateOutputType = { + id: number | null + impactRank: number | null +} + +export type NewsSumAggregateOutputType = { + id: number | null + impactRank: number | null +} + +export type NewsMinAggregateOutputType = { + id: number | null + title: string | null + summary: string | null + source: string | null + url: string | null + publishedAt: Date | null + impactRank: number | null + createdAt: Date | null +} + +export type NewsMaxAggregateOutputType = { + id: number | null + title: string | null + summary: string | null + source: string | null + url: string | null + publishedAt: Date | null + impactRank: number | null + createdAt: Date | null +} + +export type NewsCountAggregateOutputType = { + id: number + title: number + summary: number + source: number + url: number + publishedAt: number + impactRank: number + createdAt: number + _all: number +} + + +export type NewsAvgAggregateInputType = { + id?: true + impactRank?: true +} + +export type NewsSumAggregateInputType = { + id?: true + impactRank?: true +} + +export type NewsMinAggregateInputType = { + id?: true + title?: true + summary?: true + source?: true + url?: true + publishedAt?: true + impactRank?: true + createdAt?: true +} + +export type NewsMaxAggregateInputType = { + id?: true + title?: true + summary?: true + source?: true + url?: true + publishedAt?: true + impactRank?: true + createdAt?: true +} + +export type NewsCountAggregateInputType = { + id?: true + title?: true + summary?: true + source?: true + url?: true + publishedAt?: true + impactRank?: true + createdAt?: true + _all?: true +} + +export type NewsAggregateArgs = { + /** + * Filter which News to aggregate. + */ + where?: Prisma.NewsWhereInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/sorting Sorting Docs} + * + * Determine the order of News to fetch. + */ + orderBy?: Prisma.NewsOrderByWithRelationInput | Prisma.NewsOrderByWithRelationInput[] + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination#cursor-based-pagination Cursor Docs} + * + * Sets the start position + */ + cursor?: Prisma.NewsWhereUniqueInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Take `±n` News from the position of the cursor. + */ + take?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Skip the first `n` News. + */ + skip?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Count returned News + **/ + _count?: true | NewsCountAggregateInputType + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Select which fields to average + **/ + _avg?: NewsAvgAggregateInputType + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Select which fields to sum + **/ + _sum?: NewsSumAggregateInputType + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Select which fields to find the minimum value + **/ + _min?: NewsMinAggregateInputType + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Select which fields to find the maximum value + **/ + _max?: NewsMaxAggregateInputType +} + +export type GetNewsAggregateType = { + [P in keyof T & keyof AggregateNews]: P extends '_count' | 'count' + ? T[P] extends true + ? number + : Prisma.GetScalarType + : Prisma.GetScalarType +} + + + + +export type NewsGroupByArgs = { + where?: Prisma.NewsWhereInput + orderBy?: Prisma.NewsOrderByWithAggregationInput | Prisma.NewsOrderByWithAggregationInput[] + by: Prisma.NewsScalarFieldEnum[] | Prisma.NewsScalarFieldEnum + having?: Prisma.NewsScalarWhereWithAggregatesInput + take?: number + skip?: number + _count?: NewsCountAggregateInputType | true + _avg?: NewsAvgAggregateInputType + _sum?: NewsSumAggregateInputType + _min?: NewsMinAggregateInputType + _max?: NewsMaxAggregateInputType +} + +export type NewsGroupByOutputType = { + id: number + title: string + summary: string + source: string + url: string + publishedAt: Date + impactRank: number + createdAt: Date + _count: NewsCountAggregateOutputType | null + _avg: NewsAvgAggregateOutputType | null + _sum: NewsSumAggregateOutputType | null + _min: NewsMinAggregateOutputType | null + _max: NewsMaxAggregateOutputType | null +} + +export type GetNewsGroupByPayload = Prisma.PrismaPromise< + Array< + Prisma.PickEnumerable & + { + [P in ((keyof T) & (keyof NewsGroupByOutputType))]: P extends '_count' + ? T[P] extends boolean + ? number + : Prisma.GetScalarType + : Prisma.GetScalarType + } + > + > + + + +export type NewsWhereInput = { + AND?: Prisma.NewsWhereInput | Prisma.NewsWhereInput[] + OR?: Prisma.NewsWhereInput[] + NOT?: Prisma.NewsWhereInput | Prisma.NewsWhereInput[] + id?: Prisma.IntFilter<"News"> | number + title?: Prisma.StringFilter<"News"> | string + summary?: Prisma.StringFilter<"News"> | string + source?: Prisma.StringFilter<"News"> | string + url?: Prisma.StringFilter<"News"> | string + publishedAt?: Prisma.DateTimeFilter<"News"> | Date | string + impactRank?: Prisma.IntFilter<"News"> | number + createdAt?: Prisma.DateTimeFilter<"News"> | Date | string +} + +export type NewsOrderByWithRelationInput = { + id?: Prisma.SortOrder + title?: Prisma.SortOrder + summary?: Prisma.SortOrder + source?: Prisma.SortOrder + url?: Prisma.SortOrder + publishedAt?: Prisma.SortOrder + impactRank?: Prisma.SortOrder + createdAt?: Prisma.SortOrder + _relevance?: Prisma.NewsOrderByRelevanceInput +} + +export type NewsWhereUniqueInput = Prisma.AtLeast<{ + id?: number + title_publishedAt?: Prisma.NewsTitlePublishedAtCompoundUniqueInput + AND?: Prisma.NewsWhereInput | Prisma.NewsWhereInput[] + OR?: Prisma.NewsWhereInput[] + NOT?: Prisma.NewsWhereInput | Prisma.NewsWhereInput[] + title?: Prisma.StringFilter<"News"> | string + summary?: Prisma.StringFilter<"News"> | string + source?: Prisma.StringFilter<"News"> | string + url?: Prisma.StringFilter<"News"> | string + publishedAt?: Prisma.DateTimeFilter<"News"> | Date | string + impactRank?: Prisma.IntFilter<"News"> | number + createdAt?: Prisma.DateTimeFilter<"News"> | Date | string +}, "id" | "title_publishedAt"> + +export type NewsOrderByWithAggregationInput = { + id?: Prisma.SortOrder + title?: Prisma.SortOrder + summary?: Prisma.SortOrder + source?: Prisma.SortOrder + url?: Prisma.SortOrder + publishedAt?: Prisma.SortOrder + impactRank?: Prisma.SortOrder + createdAt?: Prisma.SortOrder + _count?: Prisma.NewsCountOrderByAggregateInput + _avg?: Prisma.NewsAvgOrderByAggregateInput + _max?: Prisma.NewsMaxOrderByAggregateInput + _min?: Prisma.NewsMinOrderByAggregateInput + _sum?: Prisma.NewsSumOrderByAggregateInput +} + +export type NewsScalarWhereWithAggregatesInput = { + AND?: Prisma.NewsScalarWhereWithAggregatesInput | Prisma.NewsScalarWhereWithAggregatesInput[] + OR?: Prisma.NewsScalarWhereWithAggregatesInput[] + NOT?: Prisma.NewsScalarWhereWithAggregatesInput | Prisma.NewsScalarWhereWithAggregatesInput[] + id?: Prisma.IntWithAggregatesFilter<"News"> | number + title?: Prisma.StringWithAggregatesFilter<"News"> | string + summary?: Prisma.StringWithAggregatesFilter<"News"> | string + source?: Prisma.StringWithAggregatesFilter<"News"> | string + url?: Prisma.StringWithAggregatesFilter<"News"> | string + publishedAt?: Prisma.DateTimeWithAggregatesFilter<"News"> | Date | string + impactRank?: Prisma.IntWithAggregatesFilter<"News"> | number + createdAt?: Prisma.DateTimeWithAggregatesFilter<"News"> | Date | string +} + +export type NewsCreateInput = { + title: string + summary?: string + source?: string + url?: string + publishedAt: Date | string + impactRank: number + createdAt?: Date | string +} + +export type NewsUncheckedCreateInput = { + id?: number + title: string + summary?: string + source?: string + url?: string + publishedAt: Date | string + impactRank: number + createdAt?: Date | string +} + +export type NewsUpdateInput = { + title?: Prisma.StringFieldUpdateOperationsInput | string + summary?: Prisma.StringFieldUpdateOperationsInput | string + source?: Prisma.StringFieldUpdateOperationsInput | string + url?: Prisma.StringFieldUpdateOperationsInput | string + publishedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + impactRank?: Prisma.IntFieldUpdateOperationsInput | number + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string +} + +export type NewsUncheckedUpdateInput = { + id?: Prisma.IntFieldUpdateOperationsInput | number + title?: Prisma.StringFieldUpdateOperationsInput | string + summary?: Prisma.StringFieldUpdateOperationsInput | string + source?: Prisma.StringFieldUpdateOperationsInput | string + url?: Prisma.StringFieldUpdateOperationsInput | string + publishedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + impactRank?: Prisma.IntFieldUpdateOperationsInput | number + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string +} + +export type NewsCreateManyInput = { + id?: number + title: string + summary?: string + source?: string + url?: string + publishedAt: Date | string + impactRank: number + createdAt?: Date | string +} + +export type NewsUpdateManyMutationInput = { + title?: Prisma.StringFieldUpdateOperationsInput | string + summary?: Prisma.StringFieldUpdateOperationsInput | string + source?: Prisma.StringFieldUpdateOperationsInput | string + url?: Prisma.StringFieldUpdateOperationsInput | string + publishedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + impactRank?: Prisma.IntFieldUpdateOperationsInput | number + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string +} + +export type NewsUncheckedUpdateManyInput = { + id?: Prisma.IntFieldUpdateOperationsInput | number + title?: Prisma.StringFieldUpdateOperationsInput | string + summary?: Prisma.StringFieldUpdateOperationsInput | string + source?: Prisma.StringFieldUpdateOperationsInput | string + url?: Prisma.StringFieldUpdateOperationsInput | string + publishedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + impactRank?: Prisma.IntFieldUpdateOperationsInput | number + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string +} + +export type NewsOrderByRelevanceInput = { + fields: Prisma.NewsOrderByRelevanceFieldEnum | Prisma.NewsOrderByRelevanceFieldEnum[] + sort: Prisma.SortOrder + search: string +} + +export type NewsTitlePublishedAtCompoundUniqueInput = { + title: string + publishedAt: Date | string +} + +export type NewsCountOrderByAggregateInput = { + id?: Prisma.SortOrder + title?: Prisma.SortOrder + summary?: Prisma.SortOrder + source?: Prisma.SortOrder + url?: Prisma.SortOrder + publishedAt?: Prisma.SortOrder + impactRank?: Prisma.SortOrder + createdAt?: Prisma.SortOrder +} + +export type NewsAvgOrderByAggregateInput = { + id?: Prisma.SortOrder + impactRank?: Prisma.SortOrder +} + +export type NewsMaxOrderByAggregateInput = { + id?: Prisma.SortOrder + title?: Prisma.SortOrder + summary?: Prisma.SortOrder + source?: Prisma.SortOrder + url?: Prisma.SortOrder + publishedAt?: Prisma.SortOrder + impactRank?: Prisma.SortOrder + createdAt?: Prisma.SortOrder +} + +export type NewsMinOrderByAggregateInput = { + id?: Prisma.SortOrder + title?: Prisma.SortOrder + summary?: Prisma.SortOrder + source?: Prisma.SortOrder + url?: Prisma.SortOrder + publishedAt?: Prisma.SortOrder + impactRank?: Prisma.SortOrder + createdAt?: Prisma.SortOrder +} + +export type NewsSumOrderByAggregateInput = { + id?: Prisma.SortOrder + impactRank?: Prisma.SortOrder +} + + + +export type NewsSelect = runtime.Types.Extensions.GetSelect<{ + id?: boolean + title?: boolean + summary?: boolean + source?: boolean + url?: boolean + publishedAt?: boolean + impactRank?: boolean + createdAt?: boolean +}, ExtArgs["result"]["news"]> + + + +export type NewsSelectScalar = { + id?: boolean + title?: boolean + summary?: boolean + source?: boolean + url?: boolean + publishedAt?: boolean + impactRank?: boolean + createdAt?: boolean +} + +export type NewsOmit = runtime.Types.Extensions.GetOmit<"id" | "title" | "summary" | "source" | "url" | "publishedAt" | "impactRank" | "createdAt", ExtArgs["result"]["news"]> + +export type $NewsPayload = { + name: "News" + objects: {} + scalars: runtime.Types.Extensions.GetPayloadResult<{ + id: number + title: string + summary: string + source: string + url: string + publishedAt: Date + impactRank: number + createdAt: Date + }, ExtArgs["result"]["news"]> + composites: {} +} + +export type NewsGetPayload = runtime.Types.Result.GetResult + +export type NewsCountArgs = + Omit & { + select?: NewsCountAggregateInputType | true + } + +export interface NewsDelegate { + [K: symbol]: { types: Prisma.TypeMap['model']['News'], meta: { name: 'News' } } + /** + * Find zero or one News that matches the filter. + * @param {NewsFindUniqueArgs} args - Arguments to find a News + * @example + * // Get one News + * const news = await prisma.news.findUnique({ + * where: { + * // ... provide filter here + * } + * }) + */ + findUnique(args: Prisma.SelectSubset>): Prisma.Prisma__NewsClient, T, "findUnique", GlobalOmitOptions> | null, null, ExtArgs, GlobalOmitOptions> + + /** + * Find one News that matches the filter or throw an error with `error.code='P2025'` + * if no matches were found. + * @param {NewsFindUniqueOrThrowArgs} args - Arguments to find a News + * @example + * // Get one News + * const news = await prisma.news.findUniqueOrThrow({ + * where: { + * // ... provide filter here + * } + * }) + */ + findUniqueOrThrow(args: Prisma.SelectSubset>): Prisma.Prisma__NewsClient, T, "findUniqueOrThrow", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + /** + * Find the first News that matches the filter. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {NewsFindFirstArgs} args - Arguments to find a News + * @example + * // Get one News + * const news = await prisma.news.findFirst({ + * where: { + * // ... provide filter here + * } + * }) + */ + findFirst(args?: Prisma.SelectSubset>): Prisma.Prisma__NewsClient, T, "findFirst", GlobalOmitOptions> | null, null, ExtArgs, GlobalOmitOptions> + + /** + * Find the first News that matches the filter or + * throw `PrismaKnownClientError` with `P2025` code if no matches were found. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {NewsFindFirstOrThrowArgs} args - Arguments to find a News + * @example + * // Get one News + * const news = await prisma.news.findFirstOrThrow({ + * where: { + * // ... provide filter here + * } + * }) + */ + findFirstOrThrow(args?: Prisma.SelectSubset>): Prisma.Prisma__NewsClient, T, "findFirstOrThrow", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + /** + * Find zero or more News that matches the filter. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {NewsFindManyArgs} args - Arguments to filter and select certain fields only. + * @example + * // Get all News + * const news = await prisma.news.findMany() + * + * // Get first 10 News + * const news = await prisma.news.findMany({ take: 10 }) + * + * // Only select the `id` + * const newsWithIdOnly = await prisma.news.findMany({ select: { id: true } }) + * + */ + findMany(args?: Prisma.SelectSubset>): Prisma.PrismaPromise, T, "findMany", GlobalOmitOptions>> + + /** + * Create a News. + * @param {NewsCreateArgs} args - Arguments to create a News. + * @example + * // Create one News + * const News = await prisma.news.create({ + * data: { + * // ... data to create a News + * } + * }) + * + */ + create(args: Prisma.SelectSubset>): Prisma.Prisma__NewsClient, T, "create", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + /** + * Create many News. + * @param {NewsCreateManyArgs} args - Arguments to create many News. + * @example + * // Create many News + * const news = await prisma.news.createMany({ + * data: [ + * // ... provide data here + * ] + * }) + * + */ + createMany(args?: Prisma.SelectSubset>): Prisma.PrismaPromise + + /** + * Delete a News. + * @param {NewsDeleteArgs} args - Arguments to delete one News. + * @example + * // Delete one News + * const News = await prisma.news.delete({ + * where: { + * // ... filter to delete one News + * } + * }) + * + */ + delete(args: Prisma.SelectSubset>): Prisma.Prisma__NewsClient, T, "delete", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + /** + * Update one News. + * @param {NewsUpdateArgs} args - Arguments to update one News. + * @example + * // Update one News + * const news = await prisma.news.update({ + * where: { + * // ... provide filter here + * }, + * data: { + * // ... provide data here + * } + * }) + * + */ + update(args: Prisma.SelectSubset>): Prisma.Prisma__NewsClient, T, "update", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + /** + * Delete zero or more News. + * @param {NewsDeleteManyArgs} args - Arguments to filter News to delete. + * @example + * // Delete a few News + * const { count } = await prisma.news.deleteMany({ + * where: { + * // ... provide filter here + * } + * }) + * + */ + deleteMany(args?: Prisma.SelectSubset>): Prisma.PrismaPromise + + /** + * Update zero or more News. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {NewsUpdateManyArgs} args - Arguments to update one or more rows. + * @example + * // Update many News + * const news = await prisma.news.updateMany({ + * where: { + * // ... provide filter here + * }, + * data: { + * // ... provide data here + * } + * }) + * + */ + updateMany(args: Prisma.SelectSubset>): Prisma.PrismaPromise + + /** + * Create or update one News. + * @param {NewsUpsertArgs} args - Arguments to update or create a News. + * @example + * // Update or create a News + * const news = await prisma.news.upsert({ + * create: { + * // ... data to create a News + * }, + * update: { + * // ... in case it already exists, update + * }, + * where: { + * // ... the filter for the News we want to update + * } + * }) + */ + upsert(args: Prisma.SelectSubset>): Prisma.Prisma__NewsClient, T, "upsert", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + + /** + * Count the number of News. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {NewsCountArgs} args - Arguments to filter News to count. + * @example + * // Count the number of News + * const count = await prisma.news.count({ + * where: { + * // ... the filter for the News we want to count + * } + * }) + **/ + count( + args?: Prisma.Subset, + ): Prisma.PrismaPromise< + T extends runtime.Types.Utils.Record<'select', any> + ? T['select'] extends true + ? number + : Prisma.GetScalarType + : number + > + + /** + * Allows you to perform aggregations operations on a News. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {NewsAggregateArgs} args - Select which aggregations you would like to apply and on what fields. + * @example + * // Ordered by age ascending + * // Where email contains prisma.io + * // Limited to the 10 users + * const aggregations = await prisma.user.aggregate({ + * _avg: { + * age: true, + * }, + * where: { + * email: { + * contains: "prisma.io", + * }, + * }, + * orderBy: { + * age: "asc", + * }, + * take: 10, + * }) + **/ + aggregate(args: Prisma.Subset): Prisma.PrismaPromise> + + /** + * Group by News. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {NewsGroupByArgs} args - Group by arguments. + * @example + * // Group by city, order by createdAt, get count + * const result = await prisma.user.groupBy({ + * by: ['city', 'createdAt'], + * orderBy: { + * createdAt: true + * }, + * _count: { + * _all: true + * }, + * }) + * + **/ + groupBy< + T extends NewsGroupByArgs, + HasSelectOrTake extends Prisma.Or< + Prisma.Extends<'skip', Prisma.Keys>, + Prisma.Extends<'take', Prisma.Keys> + >, + OrderByArg extends Prisma.True extends HasSelectOrTake + ? { orderBy: NewsGroupByArgs['orderBy'] } + : { orderBy?: NewsGroupByArgs['orderBy'] }, + OrderFields extends Prisma.ExcludeUnderscoreKeys>>, + ByFields extends Prisma.MaybeTupleToUnion, + ByValid extends Prisma.Has, + HavingFields extends Prisma.GetHavingFields, + HavingValid extends Prisma.Has, + ByEmpty extends T['by'] extends never[] ? Prisma.True : Prisma.False, + InputErrors extends ByEmpty extends Prisma.True + ? `Error: "by" must not be empty.` + : HavingValid extends Prisma.False + ? { + [P in HavingFields]: P extends ByFields + ? never + : P extends string + ? `Error: Field "${P}" used in "having" needs to be provided in "by".` + : [ + Error, + 'Field ', + P, + ` in "having" needs to be provided in "by"`, + ] + }[HavingFields] + : 'take' extends Prisma.Keys + ? 'orderBy' extends Prisma.Keys + ? ByValid extends Prisma.True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + : 'Error: If you provide "take", you also need to provide "orderBy"' + : 'skip' extends Prisma.Keys + ? 'orderBy' extends Prisma.Keys + ? ByValid extends Prisma.True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + : 'Error: If you provide "skip", you also need to provide "orderBy"' + : ByValid extends Prisma.True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + >(args: Prisma.SubsetIntersection & InputErrors): {} extends InputErrors ? GetNewsGroupByPayload : Prisma.PrismaPromise +/** + * Fields of the News model + */ +readonly fields: NewsFieldRefs; +} + +/** + * The delegate class that acts as a "Promise-like" for News. + * Why is this prefixed with `Prisma__`? + * Because we want to prevent naming conflicts as mentioned in + * https://github.com/prisma/prisma-client-js/issues/707 + */ +export interface Prisma__NewsClient extends Prisma.PrismaPromise { + readonly [Symbol.toStringTag]: "PrismaPromise" + /** + * Attaches callbacks for the resolution and/or rejection of the Promise. + * @param onfulfilled The callback to execute when the Promise is resolved. + * @param onrejected The callback to execute when the Promise is rejected. + * @returns A Promise for the completion of which ever callback is executed. + */ + then(onfulfilled?: ((value: T) => TResult1 | PromiseLike) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike) | undefined | null): runtime.Types.Utils.JsPromise + /** + * Attaches a callback for only the rejection of the Promise. + * @param onrejected The callback to execute when the Promise is rejected. + * @returns A Promise for the completion of the callback. + */ + catch(onrejected?: ((reason: any) => TResult | PromiseLike) | undefined | null): runtime.Types.Utils.JsPromise + /** + * Attaches a callback that is invoked when the Promise is settled (fulfilled or rejected). The + * resolved value cannot be modified from the callback. + * @param onfinally The callback to execute when the Promise is settled (fulfilled or rejected). + * @returns A Promise for the completion of the callback. + */ + finally(onfinally?: (() => void) | undefined | null): runtime.Types.Utils.JsPromise +} + + + + +/** + * Fields of the News model + */ +export interface NewsFieldRefs { + readonly id: Prisma.FieldRef<"News", 'Int'> + readonly title: Prisma.FieldRef<"News", 'String'> + readonly summary: Prisma.FieldRef<"News", 'String'> + readonly source: Prisma.FieldRef<"News", 'String'> + readonly url: Prisma.FieldRef<"News", 'String'> + readonly publishedAt: Prisma.FieldRef<"News", 'DateTime'> + readonly impactRank: Prisma.FieldRef<"News", 'Int'> + readonly createdAt: Prisma.FieldRef<"News", 'DateTime'> +} + + +// Custom InputTypes +/** + * News findUnique + */ +export type NewsFindUniqueArgs = { + /** + * Select specific fields to fetch from the News + */ + select?: Prisma.NewsSelect | null + /** + * Omit specific fields from the News + */ + omit?: Prisma.NewsOmit | null + /** + * Filter, which News to fetch. + */ + where: Prisma.NewsWhereUniqueInput +} + +/** + * News findUniqueOrThrow + */ +export type NewsFindUniqueOrThrowArgs = { + /** + * Select specific fields to fetch from the News + */ + select?: Prisma.NewsSelect | null + /** + * Omit specific fields from the News + */ + omit?: Prisma.NewsOmit | null + /** + * Filter, which News to fetch. + */ + where: Prisma.NewsWhereUniqueInput +} + +/** + * News findFirst + */ +export type NewsFindFirstArgs = { + /** + * Select specific fields to fetch from the News + */ + select?: Prisma.NewsSelect | null + /** + * Omit specific fields from the News + */ + omit?: Prisma.NewsOmit | null + /** + * Filter, which News to fetch. + */ + where?: Prisma.NewsWhereInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/sorting Sorting Docs} + * + * Determine the order of News to fetch. + */ + orderBy?: Prisma.NewsOrderByWithRelationInput | Prisma.NewsOrderByWithRelationInput[] + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination#cursor-based-pagination Cursor Docs} + * + * Sets the position for searching for News. + */ + cursor?: Prisma.NewsWhereUniqueInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Take `±n` News from the position of the cursor. + */ + take?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Skip the first `n` News. + */ + skip?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/distinct Distinct Docs} + * + * Filter by unique combinations of News. + */ + distinct?: Prisma.NewsScalarFieldEnum | Prisma.NewsScalarFieldEnum[] +} + +/** + * News findFirstOrThrow + */ +export type NewsFindFirstOrThrowArgs = { + /** + * Select specific fields to fetch from the News + */ + select?: Prisma.NewsSelect | null + /** + * Omit specific fields from the News + */ + omit?: Prisma.NewsOmit | null + /** + * Filter, which News to fetch. + */ + where?: Prisma.NewsWhereInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/sorting Sorting Docs} + * + * Determine the order of News to fetch. + */ + orderBy?: Prisma.NewsOrderByWithRelationInput | Prisma.NewsOrderByWithRelationInput[] + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination#cursor-based-pagination Cursor Docs} + * + * Sets the position for searching for News. + */ + cursor?: Prisma.NewsWhereUniqueInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Take `±n` News from the position of the cursor. + */ + take?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Skip the first `n` News. + */ + skip?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/distinct Distinct Docs} + * + * Filter by unique combinations of News. + */ + distinct?: Prisma.NewsScalarFieldEnum | Prisma.NewsScalarFieldEnum[] +} + +/** + * News findMany + */ +export type NewsFindManyArgs = { + /** + * Select specific fields to fetch from the News + */ + select?: Prisma.NewsSelect | null + /** + * Omit specific fields from the News + */ + omit?: Prisma.NewsOmit | null + /** + * Filter, which News to fetch. + */ + where?: Prisma.NewsWhereInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/sorting Sorting Docs} + * + * Determine the order of News to fetch. + */ + orderBy?: Prisma.NewsOrderByWithRelationInput | Prisma.NewsOrderByWithRelationInput[] + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination#cursor-based-pagination Cursor Docs} + * + * Sets the position for listing News. + */ + cursor?: Prisma.NewsWhereUniqueInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Take `±n` News from the position of the cursor. + */ + take?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Skip the first `n` News. + */ + skip?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/distinct Distinct Docs} + * + * Filter by unique combinations of News. + */ + distinct?: Prisma.NewsScalarFieldEnum | Prisma.NewsScalarFieldEnum[] +} + +/** + * News create + */ +export type NewsCreateArgs = { + /** + * Select specific fields to fetch from the News + */ + select?: Prisma.NewsSelect | null + /** + * Omit specific fields from the News + */ + omit?: Prisma.NewsOmit | null + /** + * The data needed to create a News. + */ + data: Prisma.XOR +} + +/** + * News createMany + */ +export type NewsCreateManyArgs = { + /** + * The data used to create many News. + */ + data: Prisma.NewsCreateManyInput | Prisma.NewsCreateManyInput[] + skipDuplicates?: boolean +} + +/** + * News update + */ +export type NewsUpdateArgs = { + /** + * Select specific fields to fetch from the News + */ + select?: Prisma.NewsSelect | null + /** + * Omit specific fields from the News + */ + omit?: Prisma.NewsOmit | null + /** + * The data needed to update a News. + */ + data: Prisma.XOR + /** + * Choose, which News to update. + */ + where: Prisma.NewsWhereUniqueInput +} + +/** + * News updateMany + */ +export type NewsUpdateManyArgs = { + /** + * The data used to update News. + */ + data: Prisma.XOR + /** + * Filter which News to update + */ + where?: Prisma.NewsWhereInput + /** + * Limit how many News to update. + */ + limit?: number +} + +/** + * News upsert + */ +export type NewsUpsertArgs = { + /** + * Select specific fields to fetch from the News + */ + select?: Prisma.NewsSelect | null + /** + * Omit specific fields from the News + */ + omit?: Prisma.NewsOmit | null + /** + * The filter to search for the News to update in case it exists. + */ + where: Prisma.NewsWhereUniqueInput + /** + * In case the News found by the `where` argument doesn't exist, create a new News with this data. + */ + create: Prisma.XOR + /** + * In case the News was found with the provided `where` argument, update it with this data. + */ + update: Prisma.XOR +} + +/** + * News delete + */ +export type NewsDeleteArgs = { + /** + * Select specific fields to fetch from the News + */ + select?: Prisma.NewsSelect | null + /** + * Omit specific fields from the News + */ + omit?: Prisma.NewsOmit | null + /** + * Filter which News to delete. + */ + where: Prisma.NewsWhereUniqueInput +} + +/** + * News deleteMany + */ +export type NewsDeleteManyArgs = { + /** + * Filter which News to delete + */ + where?: Prisma.NewsWhereInput + /** + * Limit how many News to delete. + */ + limit?: number +} + +/** + * News without action + */ +export type NewsDefaultArgs = { + /** + * Select specific fields to fetch from the News + */ + select?: Prisma.NewsSelect | null + /** + * Omit specific fields from the News + */ + omit?: Prisma.NewsOmit | null +} diff --git a/package-lock.json b/package-lock.json index 2d35305..1c0d62d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,7 @@ "jsonwebtoken": "^9.0.2", "mariadb": "^3.5.3", "marked": "^17.0.6", + "node-cron": "^3.0.3", "prisma": "^7.7.0", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -4880,6 +4881,18 @@ "node": ">= 0.6" } }, + "node_modules/node-cron": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/node-cron/-/node-cron-3.0.3.tgz", + "integrity": "sha512-dOal67//nohNgYWb+nWmg5dkFdIwDm8EpeGYMekPMrngV3637lqnX0lbUcCtgibHTz6SEz7DAIjKvKDFYCnO1A==", + "license": "ISC", + "dependencies": { + "uuid": "8.3.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/node-fetch-native": { "version": "1.6.7", "resolved": "https://registry.npmmirror.com/node-fetch-native/-/node-fetch-native-1.6.7.tgz", @@ -6134,6 +6147,15 @@ "node": ">= 0.4.0" } }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmmirror.com/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/valibot": { "version": "1.2.0", "resolved": "https://registry.npmmirror.com/valibot/-/valibot-1.2.0.tgz", diff --git a/package.json b/package.json index d8d5e34..2b5ff7f 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,8 @@ "tauri:android:dev": "tauri android dev", "tauri:android:build": "tauri android build", "tauri:android:apk": "tauri android build --apk", - "test": "echo \"Error: no test specified\" && exit 1" + "test": "echo \"Error: no test specified\" && exit 1", + "data:news": "node --no-warnings scripts/refresh-news.cjs" }, "dependencies": { "@huolala-tech/page-spy": "^1.5.7", @@ -35,6 +36,7 @@ "jsonwebtoken": "^9.0.2", "mariadb": "^3.5.3", "marked": "^17.0.6", + "node-cron": "^3.0.3", "prisma": "^7.7.0", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/prisma/migrations/20260806130000_news_and_alerts/migration.sql b/prisma/migrations/20260806130000_news_and_alerts/migration.sql new file mode 100644 index 0000000..6c9aeaa --- /dev/null +++ b/prisma/migrations/20260806130000_news_and_alerts/migration.sql @@ -0,0 +1,32 @@ +-- CreateTable +CREATE TABLE `News` ( + `id` INTEGER NOT NULL AUTO_INCREMENT, + `title` VARCHAR(191) NOT NULL, + `summary` VARCHAR(191) NOT NULL DEFAULT '', + `source` VARCHAR(191) NOT NULL DEFAULT '', + `url` VARCHAR(191) NOT NULL DEFAULT '', + `publishedAt` DATETIME(3) NOT NULL, + `impactRank` INTEGER NOT NULL, + `createdAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), + + UNIQUE INDEX `News_title_publishedAt_key`(`title`, `publishedAt`), + INDEX `News_publishedAt_idx`(`publishedAt`), + PRIMARY KEY (`id`) +) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; + +-- CreateTable +CREATE TABLE `Alert` ( + `id` INTEGER NOT NULL AUTO_INCREMENT, + `indicatorName` VARCHAR(191) NOT NULL, + `period` VARCHAR(191) NOT NULL, + `valueA` DOUBLE NOT NULL, + `valueB` DOUBLE NOT NULL, + `sourceA` VARCHAR(191) NOT NULL, + `sourceB` VARCHAR(191) NOT NULL, + `diff` DOUBLE NOT NULL, + `diffRatio` DOUBLE NOT NULL, + `createdAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), + + INDEX `Alert_createdAt_idx`(`createdAt`), + PRIMARY KEY (`id`) +) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 3514636..ec10a8d 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -66,6 +66,38 @@ model IndicatorPoint { @@unique([indicatorId, period]) } + +// 新闻: 每天 3 点由 mx_finance_search_news 拉取, 按影响大小排序, 累加多日供首页无限滚动 +model News { + id Int @id @default(autoincrement()) + title String + summary String @default("") + source String @default("") + url String @default("") + publishedAt DateTime + impactRank Int + createdAt DateTime @default(now()) + + @@unique([title, publishedAt]) + @@index([publishedAt]) +} + +// 报警: refresh 写库时比对同 (indicatorName, period) 的跨源数据, 差异超阈值记录 +model Alert { + id Int @id @default(autoincrement()) + indicatorName String + period String + valueA Float + valueB Float + sourceA String + sourceB String + diff Float + diffRatio Float + createdAt DateTime @default(now()) + + @@index([createdAt]) +} + model Econ_SowInventory { id Int @id @default(autoincrement()) month String @unique diff --git a/readme b/readme index ca41fd5..ec0ecb6 100644 --- a/readme +++ b/readme @@ -18,6 +18,7 @@ ### 报警模块 World Bank 中的数据只用来对比妙想 MCP 拉取的数据正确性。当同一时间的同一项数据不同时,记录一个报警。 - - +## 监控 +监控分为服务器监控和服务监控两部分。 +服务器监控对接 komari,地址:https://komari.honor3.com/ diff --git a/scripts/fetchers/news.fetcher.js b/scripts/fetchers/news.fetcher.js new file mode 100644 index 0000000..a963ba4 --- /dev/null +++ b/scripts/fetchers/news.fetcher.js @@ -0,0 +1,122 @@ +// 新闻 fetcher: 每天 3 点调用 mx_finance_search_news 拉国内外经济政治新闻 +// 按影响大小排序, 取前 10 条 (LLM 可能多/少几条, 全部入 DB, 按 impactRank 标记) +// 数据直接写 News 表, 与 Indicator 解耦 +import axios from 'axios' +import mysql from 'mysql2/promise' + +const MCP_BASE_DEFAULT = 'https://mxapi.eastmoney.com/mxds/mcp' +const TIMEOUT = 90000 +const TOP_N = 10 + +const QUERIES = [ + '今天国内外最新重大经济政治新闻, 按影响大小排序, 给出前 ' + TOP_N + ' 条, 每条含标题、摘要、发布时间、来源、链接', +] + +class McpClient { + constructor(baseUrl, apiKey) { this.baseUrl = baseUrl; this.apiKey = apiKey; this.id = 0 } + async _request(method, params) { + const payload = { jsonrpc: '2.0', id: ++this.id, method, ...(params ? { params } : {}) } + const resp = await axios.post(this.baseUrl, payload, { + timeout: TIMEOUT, + headers: { 'Content-Type': 'application/json', 'Accept': 'application/json, text/event-stream', 'em_api_key': this.apiKey }, + responseType: 'text', transformResponse: [(d) => d], validateStatus: () => true, + }) + if (resp.status >= 400) throw new Error('HTTP ' + resp.status + ': ' + String(resp.data).slice(0, 300)) + const parsed = JSON.parse(String(resp.data || '')) + if (parsed.error) throw new Error('MCP error ' + parsed.error.code + ': ' + parsed.error.message) + return parsed.result || parsed + } + async callTool(name, args = {}) { + const r = await this._request('tools/call', { name, arguments: args }) + if (r.isError) throw new Error('tool error: ' + (r.content || []).map((c) => c.text || '').join('; ')) + return r + } +} + +function parsePublishedAt(s) { + if (!s) return null + const d = new Date(String(s).replace(/-/g, '/')) + return isNaN(d.getTime()) ? null : d +} + +function pickNewsSheet(sheets) { + if (!Array.isArray(sheets) || sheets.length === 0) return null + return sheets.find((s) => s.sheetName && (s.sheetName.includes('资讯') || s.sheetName.includes('新闻'))) || sheets[0] +} + +// items[i] = [title, summary, publishedAt, source, url] +function parseNewsSheet(sheet, impactBase = 0) { + if (!sheet || !sheet.items) return [] + const out = [] + for (let i = 0; i < sheet.items.length; i++) { + const r = sheet.items[i] + const title = String(r[0] || '').trim() + if (!title) continue + const publishedAt = parsePublishedAt(r[2]) + if (!publishedAt) continue + out.push({ + title, + summary: String(r[1] || '').trim().slice(0, 180), + source: String(r[3] || '').trim().slice(0, 80), + url: String(r[4] || '').trim().slice(0, 400), + publishedAt, + impactRank: impactBase + i + 1, + }) + } + return out +} + +export const META = { name: 'news-mcp', description: '妙想 MCP 新闻资讯 (mx_finance_search_news)' } + +export async function fetchNewsList() { + const key = process.env.EM_API_KEY + if (!key) throw new Error('缺少 EM_API_KEY') + const base = process.env.EASTMONEY_MCP_BASE || MCP_BASE_DEFAULT + const client = new McpClient(base, key) + const all = [] + let impactBase = 0 + for (const q of QUERIES) { + try { + console.log('[News] 调用: ' + q) + const r = await client.callTool('mx_finance_search_news', { query: q }) + const text = (r.content || []).map((c) => c.text || '').join('') + const payload = JSON.parse(text) + const sheets = payload.data || (Array.isArray(payload) ? payload : [payload]) + const sheet = pickNewsSheet(sheets) + const news = parseNewsSheet(sheet, impactBase) + console.log('[News] 解析 ' + news.length + ' 条') + all.push(...news) + impactBase = all.length + } catch (e) { + console.error('[News] 拉取失败:', e.message) + } + } + return all +} + +function parseUrl(url) { + const u = new URL(url) + return { host: u.hostname, port: Number(u.port) || 3306, user: decodeURIComponent(u.username), password: decodeURIComponent(u.password), database: u.pathname.replace(/^\//, '') } +} + +export async function persistNews(newsList) { + if (!process.env.DATABASE_URL) throw new Error('缺少 DATABASE_URL') + if (!newsList || newsList.length === 0) return { inserted: 0, skipped: 0 } + const conn = await mysql.createConnection(parseUrl(process.env.DATABASE_URL)) + let inserted = 0, skipped = 0 + try { + for (const n of newsList) { + const [r] = await conn.execute( + 'INSERT INTO `News` (`title`, `summary`, `source`, `url`, `publishedAt`, `impactRank`, `createdAt`) ' + + 'VALUES (?, ?, ?, ?, ?, ?, NOW(3)) ' + + 'ON DUPLICATE KEY UPDATE `impactRank` = VALUES(`impactRank`)', + [n.title, n.summary, n.source, n.url, n.publishedAt, n.impactRank], + ) + if (r.affectedRows === 1) inserted++ + else skipped++ + } + } finally { + await conn.end() + } + return { inserted, skipped } +} \ No newline at end of file diff --git a/scripts/refresh-indicators.cjs b/scripts/refresh-indicators.cjs index 297663d..65a5021 100644 --- a/scripts/refresh-indicators.cjs +++ b/scripts/refresh-indicators.cjs @@ -147,6 +147,13 @@ async function main() { console.log('[Refresh] 同步隐藏标记: ' + names.length + ' 个指标 hidden=true (数据保留, 不展示)') } + // 6) 跨源对比报警: 全量跑一次 (即便无新指标也跑, 防止上次漏检) + try { + const m = await import('../server/alert-engine.js') + const a = await m.checkAfterRefresh(conn) + console.log('[Refresh] 报警检测: 新增 ' + a.inserted + ' 条 (扫描 ' + a.scanned + ')') + } catch (e) { console.error('[Refresh] 报警检测异常:', e.message) } + if (allItems.length === 0) { console.log('[Refresh] 无指标待写, 不写库 (DB 优先策略生效)') return @@ -163,7 +170,7 @@ async function main() { totalPoints += points console.log('[Refresh] ' + it.name + (hidden ? ' (hidden)' : '') + ': ' + points + ' 个明细点') } - console.log('[Refresh] 写入完成: ' + ins + ' 个指标有数据, ' + upd + ' 个无数据, 共 ' + totalPoints + ' 个明细点\n') + } finally { await conn.end() @@ -175,3 +182,4 @@ main().catch((e) => { process.exit(1) }) + diff --git a/scripts/refresh-news.cjs b/scripts/refresh-news.cjs new file mode 100644 index 0000000..535ec9c --- /dev/null +++ b/scripts/refresh-news.cjs @@ -0,0 +1,12 @@ +require('dotenv').config() +async function main() { + console.log('[News] 开始拉取...') + const t0 = Date.now() + const mod = await import('./fetchers/news.fetcher.js') + const list = await mod.fetchNewsList() + console.log('[News] 拉取 ' + list.length + ' 条, 耗时 ' + ((Date.now() - t0) / 1000).toFixed(1) + 's') + if (list.length === 0) { console.log('[News] 无数据, 跳过'); return } + const r = await mod.persistNews(list) + console.log('[News] 入库: 新增 ' + r.inserted + ' 条, 重复跳过 ' + r.skipped + ' 条') +} +main().catch((e) => { console.error('[News] 失败:', e); process.exit(1) }) diff --git a/server/alert-engine.js b/server/alert-engine.js new file mode 100644 index 0000000..7182973 --- /dev/null +++ b/server/alert-engine.js @@ -0,0 +1,46 @@ +import { prisma } from './db.js' + +// 跨源对比: 同 (indicatorName, period) 多源数据差异超阈值则插 Alert +// conn: mysql2 连接 +// 阈值: 绝对差 >= 0.01 且 相对差 >= 1% +// 返回 { inserted, scanned } +const ABS_TOL = 0.01 +const REL_TOL = 0.01 + +export async function checkAfterRefresh(conn) { + // conn 是 mysql2 连接, 走原始 SQL + const [rows] = await conn.execute(` + SELECT ia.name AS indicatorName, a.period, ia.source, a.value + FROM IndicatorPoint a + JOIN Indicator ia ON a.indicatorId = ia.id + ORDER BY ia.name, a.period + `) + const groups = new Map() + for (const r of rows) { + const k = r.indicatorName + '|' + r.period + if (!groups.has(k)) groups.set(k, []) + groups.get(k).push({ source: r.source, value: Number(r.value) }) + } + let inserted = 0 + for (const [k, arr] of groups) { + if (arr.length < 2) continue + const sources = new Set(arr.map((x) => x.source)) + if (sources.size < 2) continue + for (let i = 0; i < arr.length; i++) { + for (let j = i + 1; j < arr.length; j++) { + const A = arr[i], B = arr[j] + const diff = Math.abs(A.value - B.value) + const base = Math.max(Math.abs(A.value), Math.abs(B.value), 1e-9) + const ratio = diff / base + if (diff < ABS_TOL || ratio < REL_TOL) continue + const [name, period] = k.split('|') + const [r] = await conn.execute( + 'INSERT INTO `Alert` (`indicatorName`, `period`, `valueA`, `valueB`, `sourceA`, `sourceB`, `diff`, `diffRatio`, `createdAt`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, NOW(3))', + [name, period, A.value, B.value, A.source, B.source, diff, ratio], + ) + if (r.affectedRows === 1) inserted++ + } + } + } + return { inserted, scanned: rows.length } +} diff --git a/server/cron.js b/server/cron.js new file mode 100644 index 0000000..5614e8c --- /dev/null +++ b/server/cron.js @@ -0,0 +1,36 @@ +import cron from 'node-cron' +import { prisma } from './db.js' +import mysql from 'mysql2/promise' +import { fetchNewsList, persistNews } from '../scripts/fetchers/news.fetcher.js' +import { checkAfterRefresh } from './alert-engine.js' + +function parseUrl(url) { + const u = new URL(url) + return { host: u.hostname, port: Number(u.port) || 3306, user: decodeURIComponent(u.username), password: decodeURIComponent(u.password), database: u.pathname.replace(/^\//, '') } +} + +async function openConn() { + return mysql.createConnection(parseUrl(process.env.DATABASE_URL)) +} + +// 每天凌晨 3:00 (本地时间) 拉取新闻 + 跑跨源对比 +function scheduleNews() { + cron.schedule('0 3 * * *', async () => { + console.log('[cron] 3:00 触发') + try { + const list = await fetchNewsList() + const r = await persistNews(list) + console.log('[cron] 新闻入库: 新增 ' + r.inserted + ' / 跳过 ' + r.skipped) + const conn = await openConn() + try { + const a = await checkAfterRefresh(conn) + console.log('[cron] 报警检测: 新增 ' + a.inserted + ' 条 (扫描 ' + a.scanned + ')') + } finally { await conn.end() } + } catch (e) { + console.error('[cron] 任务失败:', e.message) + } + }) + console.log('[cron] 已注册: 每天 03:00 拉取新闻 + 跨源报警检测') +} + +scheduleNews() diff --git a/server/index.js b/server/index.js index de4feee..473c653 100644 --- a/server/index.js +++ b/server/index.js @@ -5,6 +5,8 @@ import express from 'express' import cors from 'cors' import authRouter from './routes/auth.js' import dataRouter from './routes/data.js' +import newsRouter from './routes/news.js' +import alertsRouter from './routes/alerts.js' import articlesRouter from './routes/articles.js' const PORT = Number(process.env.PORT) || 3001 @@ -21,6 +23,8 @@ app.get('/api/health', (_req, res) => res.json({ ok: true, ts: Date.now() })) // 业务路由 app.use('/api/auth', authRouter) app.use('/api', dataRouter) +app.use('/api', newsRouter) +app.use('/api', alertsRouter) app.use('/api', articlesRouter) // 静态资源 (Vite build 产物) @@ -41,6 +45,9 @@ app.use((err, _req, res, _next) => { res.status(500).json({ error: err.message || '服务器内部错误' }) }) +// 启动定时任务: 每天凌晨 3 点拉取新闻 +import('./cron.js').catch((e) => console.error('[cron] 加载失败:', e.message)) + app.listen(PORT, () => { console.log(`[iboard-api] listening on http://127.0.0.1:${PORT}`) console.log(`[iboard-api] static dist: ${HAS_DIST ? DIST_DIR : '(not built, API only)'}`) diff --git a/server/routes/alerts.js b/server/routes/alerts.js new file mode 100644 index 0000000..2def7f0 --- /dev/null +++ b/server/routes/alerts.js @@ -0,0 +1,24 @@ +import { Router } from 'express' +import { prisma } from '../db.js' +import { authRequired } from '../middleware.js' + +const router = Router() +router.use(authRequired) + +// 报警列表: 按时间最新优先, cursor 分页 (cursor = id) +router.get('/alerts', async (req, res, next) => { + try { + const limit = Math.min(Number(req.query.limit) || 10, 50) + const cursor = req.query.cursor ? Number(req.query.cursor) : null + const where = cursor ? { id: { lt: cursor } } : {} + const items = await prisma.alert.findMany({ + where, + orderBy: { id: 'desc' }, + take: limit, + }) + const nextCursor = items.length === limit ? String(items[items.length - 1].id) : null + res.json({ items, nextCursor }) + } catch (e) { next(e) } +}) + +export default router diff --git a/server/routes/news.js b/server/routes/news.js new file mode 100644 index 0000000..ea4157c --- /dev/null +++ b/server/routes/news.js @@ -0,0 +1,25 @@ +import { Router } from 'express' +import { prisma } from '../db.js' +import { authRequired } from '../middleware.js' + +const router = Router() +router.use(authRequired) + +// 新闻列表: 按时间最新优先, cursor 分页 (cursor = publishedAt ISO 字符串) +// 用 prisma cursor 配合 id 兜底 (同一秒发布的新闻) +router.get('/news', async (req, res, next) => { + try { + const limit = Math.min(Number(req.query.limit) || 10, 50) + const cursor = req.query.cursor || null + const where = cursor ? { publishedAt: { lt: new Date(cursor) } } : {} + const items = await prisma.news.findMany({ + where, + orderBy: [{ publishedAt: 'desc' }, { id: 'desc' }], + take: limit, + }) + const nextCursor = items.length === limit ? items[items.length - 1].publishedAt.toISOString() : null + res.json({ items, nextCursor }) + } catch (e) { next(e) } +}) + +export default router diff --git a/src/pages/HomePage.jsx b/src/pages/HomePage.jsx index 48d4491..fa56ba5 100644 --- a/src/pages/HomePage.jsx +++ b/src/pages/HomePage.jsx @@ -1,16 +1,164 @@ -import { ErrorBlock, NavBar } from 'antd-mobile' +import { useEffect, useState, useRef, useCallback } from 'react' +import { NavBar, List, Card, Empty, DotLoading } from 'antd-mobile' +import { api } from '../api/client.js' + +// 首页: 报警模块 + 新闻模块 +// - 报警: World Bank 与妙想 MCP 跨源同 (指标, 周期) 数据差异超阈值 (按时间倒序) +// - 新闻: mx_finance_search_news 每日 3 点拉取国内外经济政治新闻 (按时间倒序) +// - 两个模块均无限滚动, 触底自动加载下一页 +function fmtDateTime(s) { + if (!s) return '' + const d = new Date(s) + if (isNaN(d.getTime())) return s + const pad = (n) => String(n).padStart(2, '0') + return d.getFullYear() + '-' + pad(d.getMonth() + 1) + '-' + pad(d.getDate()) + ' ' + pad(d.getHours()) + ':' + pad(d.getMinutes()) +} +function fmtDate(s) { + if (!s) return '' + const d = new Date(s) + if (isNaN(d.getTime())) return s + const pad = (n) => String(n).padStart(2, '0') + return d.getFullYear() + '-' + pad(d.getMonth() + 1) + '-' + pad(d.getDate()) +} -// 首页: 暂留占位, 后续接入监控告警 / 个性化推荐 -// 使用 antd-mobile ErrorBlock 仿原生空状态页 export default function HomePage() { return (
首页 - +
+ + +
) -} +} + +// 报警模块 +function AlertSection() { + const [items, setItems] = useState([]) + const [loading, setLoading] = useState(false) + const [done, setDone] = useState(false) + const cursorRef = useRef(null) + const sentinelRef = useRef(null) + + const fetchPage = useCallback(async () => { + if (loading || done) return + setLoading(true) + try { + const url = '/alerts?limit=10' + (cursorRef.current ? '&cursor=' + cursorRef.current : '') + const data = await api(url) + setItems((prev) => prev.concat(data.items || [])) + cursorRef.current = data.nextCursor + if (!data.nextCursor) setDone(true) + } catch (e) { + console.error('alerts load error', e) + setDone(true) + } finally { + setLoading(false) + } + }, [loading, done]) + + useEffect(() => { fetchPage() }, []) + useEffect(() => { + if (done || items.length === 0) return + const el = sentinelRef.current + if (!el) return + const io = new IntersectionObserver((entries) => { + if (entries[0].isIntersecting) fetchPage() + }, { rootMargin: '200px' }) + io.observe(el) + return () => io.disconnect() + }, [items.length, done, fetchPage]) + + return ( +
+
报警
+ {items.length === 0 && !loading ? ( + + ) : ( +
+ {items.map((a) => ( + +
+ {a.indicatorName} + {a.period} +
+
+ {a.sourceA} = {a.valueA} vs {a.sourceB} = {a.valueB} + 差异 {(a.diffRatio * 100).toFixed(1)}% +
+
{fmtDateTime(a.createdAt)}
+
+ ))} +
+ {loading ? : (done ? '— 已加载全部 —' : '')} +
+
+ )} +
+ ) +} + +// 新闻模块 +function NewsSection() { + const [items, setItems] = useState([]) + const [loading, setLoading] = useState(false) + const [done, setDone] = useState(false) + const cursorRef = useRef(null) + const sentinelRef = useRef(null) + + const fetchPage = useCallback(async () => { + if (loading || done) return + setLoading(true) + try { + const url = '/news?limit=10' + (cursorRef.current ? '&cursor=' + encodeURIComponent(cursorRef.current) : '') + const data = await api(url) + setItems((prev) => prev.concat(data.items || [])) + cursorRef.current = data.nextCursor + if (!data.nextCursor) setDone(true) + } catch (e) { + console.error('news load error', e) + setDone(true) + } finally { + setLoading(false) + } + }, [loading, done]) + + useEffect(() => { fetchPage() }, []) + useEffect(() => { + if (done || items.length === 0) return + const el = sentinelRef.current + if (!el) return + const io = new IntersectionObserver((entries) => { + if (entries[0].isIntersecting) fetchPage() + }, { rootMargin: '200px' }) + io.observe(el) + return () => io.disconnect() + }, [items.length, done, fetchPage]) + + return ( +
+
新闻
+ {items.length === 0 && !loading ? ( + + ) : ( +
+ {items.map((n) => ( + +
{n.title}
+ {n.summary &&
{n.summary}
} +
+ {n.source || '未知来源'} + {fmtDate(n.publishedAt)} + #{n.impactRank} +
+
+ ))} +
+ {loading ? : (done ? '— 已加载全部 —' : '')} +
+
+ )} +
+ ) +} diff --git a/src/styles/globals.css b/src/styles/globals.css index aea0b77..12e4321 100644 --- a/src/styles/globals.css +++ b/src/styles/globals.css @@ -194,4 +194,24 @@ input, textarea, select { font: inherit; } .me-email { font-size: 13px; opacity: .85; } .me-list { margin-top: 12px; } .me-list .adm-list-item { padding-left: 16px; padding-right: 16px; } -.me-logout { color: var(--color-danger); } \ No newline at end of file +.me-logout { color: var(--color-danger); } +/* 首页模块: 报警 + 新闻 */ +.home-content { padding: 0 0 16px; } +.home-section { padding: 0 12px 16px; } +.section-title { font-size: 16px; font-weight: 700; padding: 14px 4px 8px; color: var(--color-text); } +.section-list { display: flex; flex-direction: column; gap: 8px; } +.alert-card.adm-card { border-radius: 10px; margin: 0; } +.alert-card .adm-card-body { padding: 10px 12px; } +.alert-title { display: flex; justify-content: space-between; font-weight: 600; font-size: 14px; } +.alert-name { color: var(--color-danger); } +.alert-period { color: var(--color-muted); font-weight: 400; } +.alert-diff { font-size: 12px; color: var(--color-text); margin-top: 4px; } +.alert-ratio { color: var(--color-danger); font-weight: 600; margin-left: 6px; } +.alert-time { font-size: 11px; color: var(--color-muted); margin-top: 4px; } +.news-card.adm-card { border-radius: 10px; margin: 0; } +.news-card .adm-card-body { padding: 10px 12px; } +.news-title { font-size: 14px; font-weight: 600; line-height: 1.4; color: var(--color-text); } +.news-summary { font-size: 12px; color: var(--color-muted); margin-top: 4px; line-height: 1.5; max-height: 3.6em; overflow: hidden; } +.news-meta { display: flex; gap: 10px; font-size: 11px; color: var(--color-muted); margin-top: 6px; } +.news-rank { color: var(--color-primary); font-weight: 600; } +.scroll-sentinel { text-align: center; padding: 14px 0 4px; color: var(--color-muted); font-size: 12px; }