diff --git a/.gitignore b/.gitignore index e668ce3..2cca39d 100644 --- a/.gitignore +++ b/.gitignore @@ -37,3 +37,8 @@ dist/* .reasonix/* # OTA 升级: 产物 (运行时生成, 部署时单独管理) + 私钥 (绝不能提交) ota-package/ + +# apizero 文件缓存 (运行时按需生成) +cache/apizero/ +# Dockerfile 持久卷挂载点 (跟 ota-package 同类) +.cache/ diff --git a/_server.err b/_server.err new file mode 100644 index 0000000..1a45562 --- /dev/null +++ b/_server.err @@ -0,0 +1,24 @@ +node:events:497 + throw er; // Unhandled 'error' event + ^ + +Error: listen EADDRINUSE: address already in use :::3001 + at Server.setupListenHandle [as _listen2] (node:net:1940:16) + at listenInCluster (node:net:1997:12) + at Server.listen (node:net:2102:7) + at Function.listen (D:\workbench\iboard\node_modules\express\lib\application.js:635:24) + at file:///D:/workbench/iboard/server/index.js:57:5 + at ModuleJob.run (node:internal/modules/esm/module_job:345:25) + at async onImport.tracePromise.__proto__ (node:internal/modules/esm/loader:651:26) + at async asyncRunEntryPointWithESMLoader (node:internal/modules/run_main:117:5) +Emitted 'error' event on Server instance at: + at emitErrorNT (node:net:1976:8) + at process.processTicksAndRejections (node:internal/process/task_queues:90:21) { + code: 'EADDRINUSE', + errno: -4091, + syscall: 'listen', + address: '::', + port: 3001 +} + +Node.js v22.19.0 diff --git a/_server.out b/_server.out new file mode 100644 index 0000000..d612097 --- /dev/null +++ b/_server.out @@ -0,0 +1,2 @@ +[cron] 已注册: 每天 03:00 拉取新闻 + 跨源报警检测 +[cron] 已注册: 每天 04:00 浙江油价历史抓取 diff --git a/generated/prisma/browser.ts b/generated/prisma/browser.ts index 94120b6..209e28b 100644 --- a/generated/prisma/browser.ts +++ b/generated/prisma/browser.ts @@ -77,3 +77,8 @@ export type Econ_SowInventory = Prisma.Econ_SowInventoryModel * */ export type ScraperCache = Prisma.ScraperCacheModel +/** + * Model OilPriceHistory + * + */ +export type OilPriceHistory = Prisma.OilPriceHistoryModel diff --git a/generated/prisma/client.ts b/generated/prisma/client.ts index b6057bb..3e172a1 100644 --- a/generated/prisma/client.ts +++ b/generated/prisma/client.ts @@ -101,3 +101,8 @@ export type Econ_SowInventory = Prisma.Econ_SowInventoryModel * */ export type ScraperCache = Prisma.ScraperCacheModel +/** + * Model OilPriceHistory + * + */ +export type OilPriceHistory = Prisma.OilPriceHistoryModel diff --git a/generated/prisma/internal/class.ts b/generated/prisma/internal/class.ts index 1076c79..41977bd 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\n// 新闻: 每天 3 点由 mx_finance_search_news 拉取, 按影响大小排序, 累加多日供首页无限滚动\nmodel News {\n id Int @id @default(autoincrement())\n title String\n summary String @default(\"\")\n content String? @db.Text\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\n// 服务器监控: 对接 komari 公开 API\nmodel ServerNode {\n id Int @id @default(autoincrement())\n uuid String @unique\n name String\n cpuName String @default(\"\")\n os String @default(\"\")\n region String @default(\"\")\n memTotal BigInt @default(0)\n diskTotal BigInt @default(0)\n cpuCores Int @default(0)\n // 最新实时快照\n cpuUsage Float @default(0)\n ramUsed BigInt @default(0)\n swapUsed BigInt @default(0)\n load1 Float @default(0)\n load5 Float @default(0)\n load15 Float @default(0)\n diskUsed BigInt @default(0)\n netIn BigInt @default(0)\n netOut BigInt @default(0)\n uptime BigInt @default(0)\n process Int @default(0)\n connections Int @default(0)\n status String @default(\"unknown\") // online | offline | unknown\n recordedAt DateTime\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// 时序历史: 每节点每分钟一条 (komari records 1 分钟粒度)\nmodel ServerNodeHistory {\n id Int @id @default(autoincrement())\n uuid String\n period DateTime\n cpu Float @default(0)\n ram BigInt @default(0)\n load Float @default(0)\n disk BigInt @default(0)\n netIn BigInt @default(0)\n netOut BigInt @default(0)\n process Int @default(0)\n connections Int @default(0)\n createdAt DateTime @default(now())\n\n @@unique([uuid, period])\n @@index([uuid, period])\n}\n\n// 服务健康检查: 本应用自检 (健康端点 / DB / 第三方)\nmodel ServiceCheck {\n id Int @id @default(autoincrement())\n name String @unique\n url String\n status String @default(\"unknown\") // up | down | unknown\n latencyMs Int @default(0)\n message String @default(\"\")\n lastCheckAt DateTime\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\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 content String? @db.Text\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\n// 服务器监控: 对接 komari 公开 API\nmodel ServerNode {\n id Int @id @default(autoincrement())\n uuid String @unique\n name String\n cpuName String @default(\"\")\n os String @default(\"\")\n region String @default(\"\")\n memTotal BigInt @default(0)\n diskTotal BigInt @default(0)\n cpuCores Int @default(0)\n // 最新实时快照\n cpuUsage Float @default(0)\n ramUsed BigInt @default(0)\n swapUsed BigInt @default(0)\n load1 Float @default(0)\n load5 Float @default(0)\n load15 Float @default(0)\n diskUsed BigInt @default(0)\n netIn BigInt @default(0)\n netOut BigInt @default(0)\n uptime BigInt @default(0)\n process Int @default(0)\n connections Int @default(0)\n status String @default(\"unknown\") // online | offline | unknown\n recordedAt DateTime\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// 时序历史: 每节点每分钟一条 (komari records 1 分钟粒度)\nmodel ServerNodeHistory {\n id Int @id @default(autoincrement())\n uuid String\n period DateTime\n cpu Float @default(0)\n ram BigInt @default(0)\n load Float @default(0)\n disk BigInt @default(0)\n netIn BigInt @default(0)\n netOut BigInt @default(0)\n process Int @default(0)\n connections Int @default(0)\n createdAt DateTime @default(now())\n\n @@unique([uuid, period])\n @@index([uuid, period])\n}\n\n// 服务健康检查: 本应用自检 (健康端点 / DB / 第三方)\nmodel ServiceCheck {\n id Int @id @default(autoincrement())\n name String @unique\n url String\n status String @default(\"unknown\") // up | down | unknown\n latencyMs Int @default(0)\n message String @default(\"\")\n lastCheckAt DateTime\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\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\n// 浙江省油价历史 (apizero price 接口每日抓取)\n// 每天 04:00 cron 触发: 检查 schedule 里待定且 <= 昨天的调价日, 抓 price?province=浙江 存本表\n// unique (date, province, fuel) 防重复\nmodel OilPriceHistory {\n id Int @id @default(autoincrement())\n date DateTime // 调价日次日 (即数据实际抓取日)\n province String // '浙江'\n fuel String // '92' | '95' | '98' | '0'\n price Float // 油价 (元/升, 4 位小数足够)\n source String @default(\"apizero\")\n createdAt DateTime @default(now())\n\n @@unique([date, province, fuel])\n @@index([province, fuel, date])\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},\"News\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"title\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"summary\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"content\",\"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},\"ServerNode\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"uuid\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"cpuName\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"os\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"region\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"memTotal\",\"kind\":\"scalar\",\"type\":\"BigInt\"},{\"name\":\"diskTotal\",\"kind\":\"scalar\",\"type\":\"BigInt\"},{\"name\":\"cpuCores\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"cpuUsage\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"ramUsed\",\"kind\":\"scalar\",\"type\":\"BigInt\"},{\"name\":\"swapUsed\",\"kind\":\"scalar\",\"type\":\"BigInt\"},{\"name\":\"load1\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"load5\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"load15\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"diskUsed\",\"kind\":\"scalar\",\"type\":\"BigInt\"},{\"name\":\"netIn\",\"kind\":\"scalar\",\"type\":\"BigInt\"},{\"name\":\"netOut\",\"kind\":\"scalar\",\"type\":\"BigInt\"},{\"name\":\"uptime\",\"kind\":\"scalar\",\"type\":\"BigInt\"},{\"name\":\"process\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"connections\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"status\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"recordedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"ServerNodeHistory\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"uuid\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"period\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"cpu\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"ram\",\"kind\":\"scalar\",\"type\":\"BigInt\"},{\"name\":\"load\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"disk\",\"kind\":\"scalar\",\"type\":\"BigInt\"},{\"name\":\"netIn\",\"kind\":\"scalar\",\"type\":\"BigInt\"},{\"name\":\"netOut\",\"kind\":\"scalar\",\"type\":\"BigInt\"},{\"name\":\"process\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"connections\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"ServiceCheck\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"url\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"status\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"latencyMs\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"message\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"lastCheckAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"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\":\"content\",\"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},\"ServerNode\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"uuid\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"cpuName\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"os\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"region\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"memTotal\",\"kind\":\"scalar\",\"type\":\"BigInt\"},{\"name\":\"diskTotal\",\"kind\":\"scalar\",\"type\":\"BigInt\"},{\"name\":\"cpuCores\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"cpuUsage\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"ramUsed\",\"kind\":\"scalar\",\"type\":\"BigInt\"},{\"name\":\"swapUsed\",\"kind\":\"scalar\",\"type\":\"BigInt\"},{\"name\":\"load1\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"load5\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"load15\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"diskUsed\",\"kind\":\"scalar\",\"type\":\"BigInt\"},{\"name\":\"netIn\",\"kind\":\"scalar\",\"type\":\"BigInt\"},{\"name\":\"netOut\",\"kind\":\"scalar\",\"type\":\"BigInt\"},{\"name\":\"uptime\",\"kind\":\"scalar\",\"type\":\"BigInt\"},{\"name\":\"process\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"connections\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"status\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"recordedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"ServerNodeHistory\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"uuid\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"period\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"cpu\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"ram\",\"kind\":\"scalar\",\"type\":\"BigInt\"},{\"name\":\"load\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"disk\",\"kind\":\"scalar\",\"type\":\"BigInt\"},{\"name\":\"netIn\",\"kind\":\"scalar\",\"type\":\"BigInt\"},{\"name\":\"netOut\",\"kind\":\"scalar\",\"type\":\"BigInt\"},{\"name\":\"process\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"connections\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"ServiceCheck\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"url\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"status\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"latencyMs\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"message\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"lastCheckAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"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},\"OilPriceHistory\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"date\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"province\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"fuel\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"price\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"source\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"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\",\"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\",\"ServerNode.findUnique\",\"ServerNode.findUniqueOrThrow\",\"ServerNode.findFirst\",\"ServerNode.findFirstOrThrow\",\"ServerNode.findMany\",\"ServerNode.createOne\",\"ServerNode.createMany\",\"ServerNode.updateOne\",\"ServerNode.updateMany\",\"ServerNode.upsertOne\",\"ServerNode.deleteOne\",\"ServerNode.deleteMany\",\"ServerNode.groupBy\",\"ServerNode.aggregate\",\"ServerNodeHistory.findUnique\",\"ServerNodeHistory.findUniqueOrThrow\",\"ServerNodeHistory.findFirst\",\"ServerNodeHistory.findFirstOrThrow\",\"ServerNodeHistory.findMany\",\"ServerNodeHistory.createOne\",\"ServerNodeHistory.createMany\",\"ServerNodeHistory.updateOne\",\"ServerNodeHistory.updateMany\",\"ServerNodeHistory.upsertOne\",\"ServerNodeHistory.deleteOne\",\"ServerNodeHistory.deleteMany\",\"ServerNodeHistory.groupBy\",\"ServerNodeHistory.aggregate\",\"ServiceCheck.findUnique\",\"ServiceCheck.findUniqueOrThrow\",\"ServiceCheck.findFirst\",\"ServiceCheck.findFirstOrThrow\",\"ServiceCheck.findMany\",\"ServiceCheck.createOne\",\"ServiceCheck.createMany\",\"ServiceCheck.updateOne\",\"ServiceCheck.updateMany\",\"ServiceCheck.upsertOne\",\"ServiceCheck.deleteOne\",\"ServiceCheck.deleteMany\",\"ServiceCheck.groupBy\",\"ServiceCheck.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\",\"name\",\"url\",\"status\",\"latencyMs\",\"message\",\"lastCheckAt\",\"uuid\",\"period\",\"cpu\",\"ram\",\"load\",\"disk\",\"netIn\",\"netOut\",\"process\",\"connections\",\"uuid_period\",\"cpuName\",\"os\",\"region\",\"memTotal\",\"diskTotal\",\"cpuCores\",\"cpuUsage\",\"ramUsed\",\"swapUsed\",\"load1\",\"load5\",\"load15\",\"diskUsed\",\"uptime\",\"recordedAt\",\"indicatorName\",\"valueA\",\"valueB\",\"sourceA\",\"sourceB\",\"diff\",\"diffRatio\",\"title\",\"summary\",\"content\",\"source\",\"publishedAt\",\"impactRank\",\"title_publishedAt\",\"indicatorId\",\"value\",\"groupName\",\"unit\",\"frequency\",\"hidden\",\"every\",\"some\",\"none\",\"indicatorId_period\",\"description\",\"slug\",\"date\",\"email\",\"password\",\"is\",\"isNot\",\"_relevance\",\"connectOrCreate\",\"upsert\",\"createMany\",\"set\",\"disconnect\",\"delete\",\"connect\",\"updateMany\",\"deleteMany\",\"increment\",\"decrement\",\"multiply\",\"divide\"]"), - graph: "vgNiqAEJtgEAANYCADC3AQAABAAQuAEAANYCADC5AQIAAAABvgFAAKwCACG_AUAArAIAIdQBAQCqAgAhjwIBAAAAAZACAQCqAgAhAQAAAAEAIAEAAAABACAJtgEAANYCADC3AQAABAAQuAEAANYCADC5AQIAqQIAIb4BQACsAgAhvwFAAKwCACHUAQEAqgIAIY8CAQCqAgAhkAIBAKoCACEBkwIAALgDACADAAAABAAgAwAABQAwBAAAAQAgAwAAAAQAIAMAAAUAMAQAAAEAIAMAAAAEACADAAAFADAEAAABACAGuQECAAAAAb4BQAAAAAG_AUAAAAAB1AEBAAAAAY8CAQAAAAGQAgEAAAABAQgAAAkAIAa5AQIAAAABvgFAAAAAAb8BQAAAAAHUAQEAAAABjwIBAAAAAZACAQAAAAEBCAAACwAwBrkBAgDgAgAhvgFAAN8CACG_AUAA3wIAIdQBAQDdAgAhjwIBAN0CACGQAgEA3QIAIQIAAAABACAIAAANACAGuQECAOACACG-AUAA3wIAIb8BQADfAgAh1AEBAN0CACGPAgEA3QIAIZACAQDdAgAhAgAAAAQAIAgAAA8AIAMAAAABACANAAAJACAOAAANACABAAAAAQAgAQAAAAQAIAUTAACzAwAgFAAAtAMAIBUAALcDACAWAAC2AwAgFwAAtQMAIAm2AQAA1QIAMLcBAAAVABC4AQAA1QIAMLkBAgCYAgAhvgFAAJsCACG_AUAAmwIAIdQBAQCZAgAhjwIBAJkCACGQAgEAmQIAIQMAAAAEACADAAAUADASAAAVACADAAAABAAgAwAABQAwBAAAAQAgCrYBAADUAgAwtwEAABsAELgBAADUAgAwuQECAAAAAb4BQACsAgAhvwFAAKwCACH7AQEAqgIAIf0BAQCqAgAhjQIBAAAAAY4CAQCqAgAhAQAAABgAIAEAAAAYACAKtgEAANQCADC3AQAAGwAQuAEAANQCADC5AQIAqQIAIb4BQACsAgAhvwFAAKwCACH7AQEAqgIAIf0BAQCqAgAhjQIBAKoCACGOAgEAqgIAIQGTAgAAsgMAIAMAAAAbACADAAAcADAEAAAYACADAAAAGwAgAwAAHAAwBAAAGAAgAwAAABsAIAMAABwAMAQAABgAIAe5AQIAAAABvgFAAAAAAb8BQAAAAAH7AQEAAAAB_QEBAAAAAY0CAQAAAAGOAgEAAAABAQgAACAAIAe5AQIAAAABvgFAAAAAAb8BQAAAAAH7AQEAAAAB_QEBAAAAAY0CAQAAAAGOAgEAAAABAQgAACIAMAe5AQIA4AIAIb4BQADfAgAhvwFAAN8CACH7AQEA3QIAIf0BAQDdAgAhjQIBAN0CACGOAgEA3QIAIQIAAAAYACAIAAAkACAHuQECAOACACG-AUAA3wIAIb8BQADfAgAh-wEBAN0CACH9AQEA3QIAIY0CAQDdAgAhjgIBAN0CACECAAAAGwAgCAAAJgAgAwAAABgAIA0AACAAIA4AACQAIAEAAAAYACABAAAAGwAgBRMAAK0DACAUAACuAwAgFQAAsQMAIBYAALADACAXAACvAwAgCrYBAADTAgAwtwEAACwAELgBAADTAgAwuQECAJgCACG-AUAAmwIAIb8BQACbAgAh-wEBAJkCACH9AQEAmQIAIY0CAQCZAgAhjgIBAJkCACEDAAAAGwAgAwAAKwAwEgAALAAgAwAAABsAIAMAABwAMAQAABgAIAkIAADSAgAgtgEAANECADC3AQAAMgAQuAEAANECADC5AQIAAAABvgFAAKwCACG_AUAArAIAIdQBAQCqAgAhjAIBAKoCACEBAAAALwAgAQAAAC8AIAkIAADSAgAgtgEAANECADC3AQAAMgAQuAEAANECADC5AQIAqQIAIb4BQACsAgAhvwFAAKwCACHUAQEAqgIAIYwCAQCqAgAhAZMCAACsAwAgAwAAADIAIAMAADMAMAQAAC8AIAMAAAAyACADAAAzADAEAAAvACADAAAAMgAgAwAAMwAwBAAALwAgBgiAAAAAAbkBAgAAAAG-AUAAAAABvwFAAAAAAdQBAQAAAAGMAgEAAAABAQgAADcAIAYIgAAAAAG5AQIAAAABvgFAAAAAAb8BQAAAAAHUAQEAAAABjAIBAAAAAQEIAAA5ADAGCIAAAAABuQECAOACACG-AUAA3wIAIb8BQADfAgAh1AEBAN0CACGMAgEA3QIAIQIAAAAvACAIAAA7ACAGCIAAAAABuQECAOACACG-AUAA3wIAIb8BQADfAgAh1AEBAN0CACGMAgEA3QIAIQIAAAAyACAIAAA9ACADAAAALwAgDQAANwAgDgAAOwAgAQAAAC8AIAEAAAAyACAFEwAApwMAIBQAAKgDACAVAACrAwAgFgAAqgMAIBcAAKkDACAJCAAAzwIAILYBAADOAgAwtwEAAEMAELgBAADOAgAwuQECAJgCACG-AUAAmwIAIb8BQACbAgAh1AEBAJkCACGMAgEAmQIAIQMAAAAyACADAABCADASAABDACADAAAAMgAgAwAAMwAwBAAALwAgDjcAAMoCACC2AQAAyAIAMLcBAABOABC4AQAAyAIAMLkBAgAAAAG-AUAArAIAIb8BQACsAgAh1AEBAAAAAfsBAQCqAgAh_gEBAKoCACGEAgEAqgIAIYUCAQCqAgAhhgIBAKoCACGHAiAAyQIAIQEAAABGACAKNgAAzQIAILYBAADMAgAwtwEAAEgAELgBAADMAgAwuQECAKkCACG-AUAArAIAIb8BQACsAgAh2wEBAKoCACGCAgIAqQIAIYMCCAC5AgAhAjYAAKUDACCTAgAApgMAIAs2AADNAgAgtgEAAMwCADC3AQAASAAQuAEAAMwCADC5AQIAAAABvgFAAKwCACG_AUAArAIAIdsBAQCqAgAhggICAKkCACGDAggAuQIAIYsCAADLAgAgAwAAAEgAIAMAAEkAMAQAAEoAIAEAAABIACABAAAARgAgDjcAAMoCACC2AQAAyAIAMLcBAABOABC4AQAAyAIAMLkBAgCpAgAhvgFAAKwCACG_AUAArAIAIdQBAQCqAgAh-wEBAKoCACH-AQEAqgIAIYQCAQCqAgAhhQIBAKoCACGGAgEAqgIAIYcCIADJAgAhAjcAAKMDACCTAgAApAMAIAMAAABOACADAABPADAEAABGACADAAAATgAgAwAATwAwBAAARgAgAwAAAE4AIAMAAE8AMAQAAEYAIAs3AACiAwAguQECAAAAAb4BQAAAAAG_AUAAAAAB1AEBAAAAAfsBAQAAAAH-AQEAAAABhAIBAAAAAYUCAQAAAAGGAgEAAAABhwIgAAAAAQEIAABTACAKuQECAAAAAb4BQAAAAAG_AUAAAAAB1AEBAAAAAfsBAQAAAAH-AQEAAAABhAIBAAAAAYUCAQAAAAGGAgEAAAABhwIgAAAAAQEIAABVADALNwAAlQMAILkBAgDgAgAhvgFAAN8CACG_AUAA3wIAIdQBAQDdAgAh-wEBAN0CACH-AQEA3QIAIYQCAQDdAgAhhQIBAN0CACGGAgEA3QIAIYcCIACUAwAhAgAAAEYAIAgAAFcAIAq5AQIA4AIAIb4BQADfAgAhvwFAAN8CACHUAQEA3QIAIfsBAQDdAgAh_gEBAN0CACGEAgEA3QIAIYUCAQDdAgAhhgIBAN0CACGHAiAAlAMAIQIAAABOACAIAABZACADAAAARgAgDQAAUwAgDgAAVwAgAQAAAEYAIAEAAABOACAFEwAAjwMAIBQAAJADACAVAACTAwAgFgAAkgMAIBcAAJEDACANtgEAAMQCADC3AQAAXwAQuAEAAMQCADC5AQIAmAIAIb4BQACbAgAhvwFAAJsCACHUAQEAmQIAIfsBAQCZAgAh_gEBAJkCACGEAgEAmQIAIYUCAQCZAgAhhgIBAJkCACGHAiAAxQIAIQMAAABOACADAABeADASAABfACADAAAATgAgAwAATwAwBAAARgAgAQAAAEoAIAEAAABKACADAAAASAAgAwAASQAwBAAASgAgAwAAAEgAIAMAAEkAMAQAAEoAIAMAAABIACADAABJADAEAABKACAHNgAAjgMAILkBAgAAAAG-AUAAAAABvwFAAAAAAdsBAQAAAAGCAgIAAAABgwIIAAAAAQEIAABnACAGuQECAAAAAb4BQAAAAAG_AUAAAAAB2wEBAAAAAYICAgAAAAGDAggAAAABAQgAAGkAMAc2AACNAwAguQECAOACACG-AUAA3wIAIb8BQADfAgAh2wEBAN0CACGCAgIA4AIAIYMCCADzAgAhAgAAAEoAIAgAAGsAIAa5AQIA4AIAIb4BQADfAgAhvwFAAN8CACHbAQEA3QIAIYICAgDgAgAhgwIIAPMCACECAAAASAAgCAAAbQAgAwAAAEoAIA0AAGcAIA4AAGsAIAEAAABKACABAAAASAAgBRMAAIgDACAUAACJAwAgFQAAjAMAIBYAAIsDACAXAACKAwAgCbYBAADDAgAwtwEAAHMAELgBAADDAgAwuQECAJgCACG-AUAAmwIAIb8BQACbAgAh2wEBAJkCACGCAgIAmAIAIYMCCACzAgAhAwAAAEgAIAMAAHIAMBIAAHMAIAMAAABIACADAABJADAEAABKACANtgEAAMECADC3AQAAeQAQuAEAAMECADC5AQIAAAABvgFAAKwCACHVAQEAqgIAIfsBAQCqAgAh_AEBAKoCACH9AQEAqwIAIf4BAQCqAgAh_wFAAKwCACGAAgIAqQIAIYECAADCAgAgAQAAAHYAIAEAAAB2ACAMtgEAAMECADC3AQAAeQAQuAEAAMECADC5AQIAqQIAIb4BQACsAgAh1QEBAKoCACH7AQEAqgIAIfwBAQCqAgAh_QEBAKsCACH-AQEAqgIAIf8BQACsAgAhgAICAKkCACEC_QEAANcCACCTAgAAhwMAIAMAAAB5ACADAAB6ADAEAAB2ACADAAAAeQAgAwAAegAwBAAAdgAgAwAAAHkAIAMAAHoAMAQAAHYAIAm5AQIAAAABvgFAAAAAAdUBAQAAAAH7AQEAAAAB_AEBAAAAAf0BAQAAAAH-AQEAAAAB_wFAAAAAAYACAgAAAAEBCAAAfgAgCbkBAgAAAAG-AUAAAAAB1QEBAAAAAfsBAQAAAAH8AQEAAAAB_QEBAAAAAf4BAQAAAAH_AUAAAAABgAICAAAAAQEIAACAAQAwCbkBAgDgAgAhvgFAAN8CACHVAQEA3QIAIfsBAQDdAgAh_AEBAN0CACH9AQEA3gIAIf4BAQDdAgAh_wFAAN8CACGAAgIA4AIAIQIAAAB2ACAIAACCAQAgCbkBAgDgAgAhvgFAAN8CACHVAQEA3QIAIfsBAQDdAgAh_AEBAN0CACH9AQEA3gIAIf4BAQDdAgAh_wFAAN8CACGAAgIA4AIAIQIAAAB5ACAIAACEAQAgAwAAAHYAIA0AAH4AIA4AAIIBACABAAAAdgAgAQAAAHkAIAYTAACCAwAgFAAAgwMAIBUAAIYDACAWAACFAwAgFwAAhAMAIP0BAADXAgAgDLYBAADAAgAwtwEAAIoBABC4AQAAwAIAMLkBAgCYAgAhvgFAAJsCACHVAQEAmQIAIfsBAQCZAgAh_AEBAJkCACH9AQEAmgIAIf4BAQCZAgAh_wFAAJsCACGAAgIAmAIAIQMAAAB5ACADAACJAQAwEgAAigEAIAMAAAB5ACADAAB6ADAEAAB2ACANtgEAAL8CADC3AQAAkAEAELgBAAC_AgAwuQECAAAAAb4BQACsAgAh2wEBAKoCACH0AQEAqgIAIfUBCAC5AgAh9gEIALkCACH3AQEAqgIAIfgBAQCqAgAh-QEIALkCACH6AQgAuQIAIQEAAACNAQAgAQAAAI0BACANtgEAAL8CADC3AQAAkAEAELgBAAC_AgAwuQECAKkCACG-AUAArAIAIdsBAQCqAgAh9AEBAKoCACH1AQgAuQIAIfYBCAC5AgAh9wEBAKoCACH4AQEAqgIAIfkBCAC5AgAh-gEIALkCACEBkwIAAIEDACADAAAAkAEAIAMAAJEBADAEAACNAQAgAwAAAJABACADAACRAQAwBAAAjQEAIAMAAACQAQAgAwAAkQEAMAQAAI0BACAKuQECAAAAAb4BQAAAAAHbAQEAAAAB9AEBAAAAAfUBCAAAAAH2AQgAAAAB9wEBAAAAAfgBAQAAAAH5AQgAAAAB-gEIAAAAAQEIAACVAQAgCrkBAgAAAAG-AUAAAAAB2wEBAAAAAfQBAQAAAAH1AQgAAAAB9gEIAAAAAfcBAQAAAAH4AQEAAAAB-QEIAAAAAfoBCAAAAAEBCAAAlwEAMAq5AQIA4AIAIb4BQADfAgAh2wEBAN0CACH0AQEA3QIAIfUBCADzAgAh9gEIAPMCACH3AQEA3QIAIfgBAQDdAgAh-QEIAPMCACH6AQgA8wIAIQIAAACNAQAgCAAAmQEAIAq5AQIA4AIAIb4BQADfAgAh2wEBAN0CACH0AQEA3QIAIfUBCADzAgAh9gEIAPMCACH3AQEA3QIAIfgBAQDdAgAh-QEIAPMCACH6AQgA8wIAIQIAAACQAQAgCAAAmwEAIAMAAACNAQAgDQAAlQEAIA4AAJkBACABAAAAjQEAIAEAAACQAQAgBRMAAPwCACAUAAD9AgAgFQAAgAMAIBYAAP8CACAXAAD-AgAgDbYBAAC-AgAwtwEAAKEBABC4AQAAvgIAMLkBAgCYAgAhvgFAAJsCACHbAQEAmQIAIfQBAQCZAgAh9QEIALMCACH2AQgAswIAIfcBAQCZAgAh-AEBAJkCACH5AQgAswIAIfoBCACzAgAhAwAAAJABACADAACgAQAwEgAAoQEAIAMAAACQAQAgAwAAkQEAMAQAAI0BACActgEAAL0CADC3AQAApwEAELgBAAC9AgAwuQECAAAAAb4BQACsAgAhvwFAAKwCACHUAQEAqgIAIdYBAQCqAgAh2gEBAAAAAeABBAC6AgAh4QEEALoCACHiAQIAqQIAIeMBAgCpAgAh5QEBAKoCACHmAQEAqgIAIecBAQCqAgAh6AEEALoCACHpAQQAugIAIeoBAgCpAgAh6wEIALkCACHsAQQAugIAIe0BBAC6AgAh7gEIALkCACHvAQgAuQIAIfABCAC5AgAh8QEEALoCACHyAQQAugIAIfMBQACsAgAhAQAAAKQBACABAAAApAEAIBy2AQAAvQIAMLcBAACnAQAQuAEAAL0CADC5AQIAqQIAIb4BQACsAgAhvwFAAKwCACHUAQEAqgIAIdYBAQCqAgAh2gEBAKoCACHgAQQAugIAIeEBBAC6AgAh4gECAKkCACHjAQIAqQIAIeUBAQCqAgAh5gEBAKoCACHnAQEAqgIAIegBBAC6AgAh6QEEALoCACHqAQIAqQIAIesBCAC5AgAh7AEEALoCACHtAQQAugIAIe4BCAC5AgAh7wEIALkCACHwAQgAuQIAIfEBBAC6AgAh8gEEALoCACHzAUAArAIAIQGTAgAA-wIAIAMAAACnAQAgAwAAqAEAMAQAAKQBACADAAAApwEAIAMAAKgBADAEAACkAQAgAwAAAKcBACADAACoAQAwBAAApAEAIBm5AQIAAAABvgFAAAAAAb8BQAAAAAHUAQEAAAAB1gEBAAAAAdoBAQAAAAHgAQQAAAAB4QEEAAAAAeIBAgAAAAHjAQIAAAAB5QEBAAAAAeYBAQAAAAHnAQEAAAAB6AEEAAAAAekBBAAAAAHqAQIAAAAB6wEIAAAAAewBBAAAAAHtAQQAAAAB7gEIAAAAAe8BCAAAAAHwAQgAAAAB8QEEAAAAAfIBBAAAAAHzAUAAAAABAQgAAKwBACAZuQECAAAAAb4BQAAAAAG_AUAAAAAB1AEBAAAAAdYBAQAAAAHaAQEAAAAB4AEEAAAAAeEBBAAAAAHiAQIAAAAB4wECAAAAAeUBAQAAAAHmAQEAAAAB5wEBAAAAAegBBAAAAAHpAQQAAAAB6gECAAAAAesBCAAAAAHsAQQAAAAB7QEEAAAAAe4BCAAAAAHvAQgAAAAB8AEIAAAAAfEBBAAAAAHyAQQAAAAB8wFAAAAAAQEIAACuAQAwGbkBAgDgAgAhvgFAAN8CACG_AUAA3wIAIdQBAQDdAgAh1gEBAN0CACHaAQEA3QIAIeABBAD0AgAh4QEEAPQCACHiAQIA4AIAIeMBAgDgAgAh5QEBAN0CACHmAQEA3QIAIecBAQDdAgAh6AEEAPQCACHpAQQA9AIAIeoBAgDgAgAh6wEIAPMCACHsAQQA9AIAIe0BBAD0AgAh7gEIAPMCACHvAQgA8wIAIfABCADzAgAh8QEEAPQCACHyAQQA9AIAIfMBQADfAgAhAgAAAKQBACAIAACwAQAgGbkBAgDgAgAhvgFAAN8CACG_AUAA3wIAIdQBAQDdAgAh1gEBAN0CACHaAQEA3QIAIeABBAD0AgAh4QEEAPQCACHiAQIA4AIAIeMBAgDgAgAh5QEBAN0CACHmAQEA3QIAIecBAQDdAgAh6AEEAPQCACHpAQQA9AIAIeoBAgDgAgAh6wEIAPMCACHsAQQA9AIAIe0BBAD0AgAh7gEIAPMCACHvAQgA8wIAIfABCADzAgAh8QEEAPQCACHyAQQA9AIAIfMBQADfAgAhAgAAAKcBACAIAACyAQAgAwAAAKQBACANAACsAQAgDgAAsAEAIAEAAACkAQAgAQAAAKcBACAFEwAA9gIAIBQAAPcCACAVAAD6AgAgFgAA-QIAIBcAAPgCACActgEAALwCADC3AQAAuAEAELgBAAC8AgAwuQECAJgCACG-AUAAmwIAIb8BQACbAgAh1AEBAJkCACHWAQEAmQIAIdoBAQCZAgAh4AEEALQCACHhAQQAtAIAIeIBAgCYAgAh4wECAJgCACHlAQEAmQIAIeYBAQCZAgAh5wEBAJkCACHoAQQAtAIAIekBBAC0AgAh6gECAJgCACHrAQgAswIAIewBBAC0AgAh7QEEALQCACHuAQgAswIAIe8BCACzAgAh8AEIALMCACHxAQQAtAIAIfIBBAC0AgAh8wFAAJsCACEDAAAApwEAIAMAALcBADASAAC4AQAgAwAAAKcBACADAACoAQAwBAAApAEAIBC2AQAAuAIAMLcBAAC-AQAQuAEAALgCADC5AQIAAAABvgFAAKwCACHaAQEAqgIAIdsBQACsAgAh3AEIALkCACHdAQQAugIAId4BCAC5AgAh3wEEALoCACHgAQQAugIAIeEBBAC6AgAh4gECAKkCACHjAQIAqQIAIeQBAAC7AgAgAQAAALsBACABAAAAuwEAIA-2AQAAuAIAMLcBAAC-AQAQuAEAALgCADC5AQIAqQIAIb4BQACsAgAh2gEBAKoCACHbAUAArAIAIdwBCAC5AgAh3QEEALoCACHeAQgAuQIAId8BBAC6AgAh4AEEALoCACHhAQQAugIAIeIBAgCpAgAh4wECAKkCACEBkwIAAPUCACADAAAAvgEAIAMAAL8BADAEAAC7AQAgAwAAAL4BACADAAC_AQAwBAAAuwEAIAMAAAC-AQAgAwAAvwEAMAQAALsBACAMuQECAAAAAb4BQAAAAAHaAQEAAAAB2wFAAAAAAdwBCAAAAAHdAQQAAAAB3gEIAAAAAd8BBAAAAAHgAQQAAAAB4QEEAAAAAeIBAgAAAAHjAQIAAAABAQgAAMMBACAMuQECAAAAAb4BQAAAAAHaAQEAAAAB2wFAAAAAAdwBCAAAAAHdAQQAAAAB3gEIAAAAAd8BBAAAAAHgAQQAAAAB4QEEAAAAAeIBAgAAAAHjAQIAAAABAQgAAMUBADAMuQECAOACACG-AUAA3wIAIdoBAQDdAgAh2wFAAN8CACHcAQgA8wIAId0BBAD0AgAh3gEIAPMCACHfAQQA9AIAIeABBAD0AgAh4QEEAPQCACHiAQIA4AIAIeMBAgDgAgAhAgAAALsBACAIAADHAQAgDLkBAgDgAgAhvgFAAN8CACHaAQEA3QIAIdsBQADfAgAh3AEIAPMCACHdAQQA9AIAId4BCADzAgAh3wEEAPQCACHgAQQA9AIAIeEBBAD0AgAh4gECAOACACHjAQIA4AIAIQIAAAC-AQAgCAAAyQEAIAMAAAC7AQAgDQAAwwEAIA4AAMcBACABAAAAuwEAIAEAAAC-AQAgBRMAAO4CACAUAADvAgAgFQAA8gIAIBYAAPECACAXAADwAgAgD7YBAACyAgAwtwEAAM8BABC4AQAAsgIAMLkBAgCYAgAhvgFAAJsCACHaAQEAmQIAIdsBQACbAgAh3AEIALMCACHdAQQAtAIAId4BCACzAgAh3wEEALQCACHgAQQAtAIAIeEBBAC0AgAh4gECAJgCACHjAQIAmAIAIQMAAAC-AQAgAwAAzgEAMBIAAM8BACADAAAAvgEAIAMAAL8BADAEAAC7AQAgDLYBAACxAgAwtwEAANUBABC4AQAAsQIAMLkBAgAAAAG-AUAArAIAIb8BQACsAgAh1AEBAAAAAdUBAQCqAgAh1gEBAKoCACHXAQIAqQIAIdgBAQCqAgAh2QFAAKwCACEBAAAA0gEAIAEAAADSAQAgDLYBAACxAgAwtwEAANUBABC4AQAAsQIAMLkBAgCpAgAhvgFAAKwCACG_AUAArAIAIdQBAQCqAgAh1QEBAKoCACHWAQEAqgIAIdcBAgCpAgAh2AEBAKoCACHZAUAArAIAIQGTAgAA7QIAIAMAAADVAQAgAwAA1gEAMAQAANIBACADAAAA1QEAIAMAANYBADAEAADSAQAgAwAAANUBACADAADWAQAwBAAA0gEAIAm5AQIAAAABvgFAAAAAAb8BQAAAAAHUAQEAAAAB1QEBAAAAAdYBAQAAAAHXAQIAAAAB2AEBAAAAAdkBQAAAAAEBCAAA2gEAIAm5AQIAAAABvgFAAAAAAb8BQAAAAAHUAQEAAAAB1QEBAAAAAdYBAQAAAAHXAQIAAAAB2AEBAAAAAdkBQAAAAAEBCAAA3AEAMAm5AQIA4AIAIb4BQADfAgAhvwFAAN8CACHUAQEA3QIAIdUBAQDdAgAh1gEBAN0CACHXAQIA4AIAIdgBAQDdAgAh2QFAAN8CACECAAAA0gEAIAgAAN4BACAJuQECAOACACG-AUAA3wIAIb8BQADfAgAh1AEBAN0CACHVAQEA3QIAIdYBAQDdAgAh1wECAOACACHYAQEA3QIAIdkBQADfAgAhAgAAANUBACAIAADgAQAgAwAAANIBACANAADaAQAgDgAA3gEAIAEAAADSAQAgAQAAANUBACAFEwAA6AIAIBQAAOkCACAVAADsAgAgFgAA6wIAIBcAAOoCACAMtgEAALACADC3AQAA5gEAELgBAACwAgAwuQECAJgCACG-AUAAmwIAIb8BQACbAgAh1AEBAJkCACHVAQEAmQIAIdYBAQCZAgAh1wECAJgCACHYAQEAmQIAIdkBQACbAgAhAwAAANUBACADAADlAQAwEgAA5gEAIAMAAADVAQAgAwAA1gEAMAQAANIBACAItgEAAK8CADC3AQAA7AEAELgBAACvAgAwuQECAAAAAb4BQACsAgAhvwFAAKwCACHSAQEAAAAB0wECAKkCACEBAAAA6QEAIAEAAADpAQAgCLYBAACvAgAwtwEAAOwBABC4AQAArwIAMLkBAgCpAgAhvgFAAKwCACG_AUAArAIAIdIBAQCqAgAh0wECAKkCACEBkwIAAOcCACADAAAA7AEAIAMAAO0BADAEAADpAQAgAwAAAOwBACADAADtAQAwBAAA6QEAIAMAAADsAQAgAwAA7QEAMAQAAOkBACAFuQECAAAAAb4BQAAAAAG_AUAAAAAB0gEBAAAAAdMBAgAAAAEBCAAA8QEAIAW5AQIAAAABvgFAAAAAAb8BQAAAAAHSAQEAAAAB0wECAAAAAQEIAADzAQAwBbkBAgDgAgAhvgFAAN8CACG_AUAA3wIAIdIBAQDdAgAh0wECAOACACECAAAA6QEAIAgAAPUBACAFuQECAOACACG-AUAA3wIAIb8BQADfAgAh0gEBAN0CACHTAQIA4AIAIQIAAADsAQAgCAAA9wEAIAMAAADpAQAgDQAA8QEAIA4AAPUBACABAAAA6QEAIAEAAADsAQAgBRMAAOICACAUAADjAgAgFQAA5gIAIBYAAOUCACAXAADkAgAgCLYBAACuAgAwtwEAAP0BABC4AQAArgIAMLkBAgCYAgAhvgFAAJsCACG_AUAAmwIAIdIBAQCZAgAh0wECAJgCACEDAAAA7AEAIAMAAPwBADASAAD9AQAgAwAAAOwBACADAADtAQAwBAAA6QEAIAq2AQAAqAIAMLcBAACDAgAQuAEAAKgCADC5AQIAAAABugEBAAAAAbsBAQCrAgAhvAFAAKwCACG9AQAArQIAIL4BQACsAgAhvwFAAKwCACEBAAAAgAIAIAEAAACAAgAgCrYBAACoAgAwtwEAAIMCABC4AQAAqAIAMLkBAgCpAgAhugEBAKoCACG7AQEAqwIAIbwBQACsAgAhvQEAAK0CACC-AUAArAIAIb8BQACsAgAhA7sBAADXAgAgvQEAANcCACCTAgAA4QIAIAMAAACDAgAgAwAAhAIAMAQAAIACACADAAAAgwIAIAMAAIQCADAEAACAAgAgAwAAAIMCACADAACEAgAwBAAAgAIAIAe5AQIAAAABugEBAAAAAbsBAQAAAAG8AUAAAAABvQGAAAAAAb4BQAAAAAG_AUAAAAABAQgAAIgCACAHuQECAAAAAboBAQAAAAG7AQEAAAABvAFAAAAAAb0BgAAAAAG-AUAAAAABvwFAAAAAAQEIAACKAgAwB7kBAgDgAgAhugEBAN0CACG7AQEA3gIAIbwBQADfAgAhvQGAAAAAAb4BQADfAgAhvwFAAN8CACECAAAAgAIAIAgAAIwCACAHuQECAOACACG6AQEA3QIAIbsBAQDeAgAhvAFAAN8CACG9AYAAAAABvgFAAN8CACG_AUAA3wIAIQIAAACDAgAgCAAAjgIAIAMAAACAAgAgDQAAiAIAIA4AAIwCACABAAAAgAIAIAEAAACDAgAgBxMAANgCACAUAADZAgAgFQAA3AIAIBYAANsCACAXAADaAgAguwEAANcCACC9AQAA1wIAIAq2AQAAlwIAMLcBAACUAgAQuAEAAJcCADC5AQIAmAIAIboBAQCZAgAhuwEBAJoCACG8AUAAmwIAIb0BAACcAgAgvgFAAJsCACG_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_AUAAmwIAIdIBAQCZAgAh0wECAJgCACEItgEAAK8CADC3AQAA7AEAELgBAACvAgAwuQECAKkCACG-AUAArAIAIb8BQACsAgAh0gEBAKoCACHTAQIAqQIAIQy2AQAAsAIAMLcBAADmAQAQuAEAALACADC5AQIAmAIAIb4BQACbAgAhvwFAAJsCACHUAQEAmQIAIdUBAQCZAgAh1gEBAJkCACHXAQIAmAIAIdgBAQCZAgAh2QFAAJsCACEMtgEAALECADC3AQAA1QEAELgBAACxAgAwuQECAKkCACG-AUAArAIAIb8BQACsAgAh1AEBAKoCACHVAQEAqgIAIdYBAQCqAgAh1wECAKkCACHYAQEAqgIAIdkBQACsAgAhD7YBAACyAgAwtwEAAM8BABC4AQAAsgIAMLkBAgCYAgAhvgFAAJsCACHaAQEAmQIAIdsBQACbAgAh3AEIALMCACHdAQQAtAIAId4BCACzAgAh3wEEALQCACHgAQQAtAIAIeEBBAC0AgAh4gECAJgCACHjAQIAmAIAIQ0TAACgAgAgFAAApwIAIBUAAKcCACAWAACnAgAgFwAApwIAIMABCAAAAAHHAQgAAAAByAEIAAAAAckBCAAAAAHKAQgAAAABywEIALcCACHMAQgAAAAEzQEIAAAABA0TAACgAgAgFAAApwIAIBUAALYCACAWAAC2AgAgFwAAtgIAIMABBAAAAAHHAQQAAAAByAEEAAAAAckBBAAAAAHKAQQAAAABywEEALUCACHMAQQAAAAEzQEEAAAABA0TAACgAgAgFAAApwIAIBUAALYCACAWAAC2AgAgFwAAtgIAIMABBAAAAAHHAQQAAAAByAEEAAAAAckBBAAAAAHKAQQAAAABywEEALUCACHMAQQAAAAEzQEEAAAABAjAAQQAAAABxwEEAAAAAcgBBAAAAAHJAQQAAAABygEEAAAAAcsBBAC2AgAhzAEEAAAABM0BBAAAAAQNEwAAoAIAIBQAAKcCACAVAACnAgAgFgAApwIAIBcAAKcCACDAAQgAAAABxwEIAAAAAcgBCAAAAAHJAQgAAAABygEIAAAAAcsBCAC3AgAhzAEIAAAABM0BCAAAAAQPtgEAALgCADC3AQAAvgEAELgBAAC4AgAwuQECAKkCACG-AUAArAIAIdoBAQCqAgAh2wFAAKwCACHcAQgAuQIAId0BBAC6AgAh3gEIALkCACHfAQQAugIAIeABBAC6AgAh4QEEALoCACHiAQIAqQIAIeMBAgCpAgAhCMABCAAAAAHHAQgAAAAByAEIAAAAAckBCAAAAAHKAQgAAAABywEIAKcCACHMAQgAAAAEzQEIAAAABAjAAQQAAAABxwEEAAAAAcgBBAAAAAHJAQQAAAABygEEAAAAAcsBBAC2AgAhzAEEAAAABM0BBAAAAAQC2gEBAAAAAdsBQAAAAAEctgEAALwCADC3AQAAuAEAELgBAAC8AgAwuQECAJgCACG-AUAAmwIAIb8BQACbAgAh1AEBAJkCACHWAQEAmQIAIdoBAQCZAgAh4AEEALQCACHhAQQAtAIAIeIBAgCYAgAh4wECAJgCACHlAQEAmQIAIeYBAQCZAgAh5wEBAJkCACHoAQQAtAIAIekBBAC0AgAh6gECAJgCACHrAQgAswIAIewBBAC0AgAh7QEEALQCACHuAQgAswIAIe8BCACzAgAh8AEIALMCACHxAQQAtAIAIfIBBAC0AgAh8wFAAJsCACEctgEAAL0CADC3AQAApwEAELgBAAC9AgAwuQECAKkCACG-AUAArAIAIb8BQACsAgAh1AEBAKoCACHWAQEAqgIAIdoBAQCqAgAh4AEEALoCACHhAQQAugIAIeIBAgCpAgAh4wECAKkCACHlAQEAqgIAIeYBAQCqAgAh5wEBAKoCACHoAQQAugIAIekBBAC6AgAh6gECAKkCACHrAQgAuQIAIewBBAC6AgAh7QEEALoCACHuAQgAuQIAIe8BCAC5AgAh8AEIALkCACHxAQQAugIAIfIBBAC6AgAh8wFAAKwCACENtgEAAL4CADC3AQAAoQEAELgBAAC-AgAwuQECAJgCACG-AUAAmwIAIdsBAQCZAgAh9AEBAJkCACH1AQgAswIAIfYBCACzAgAh9wEBAJkCACH4AQEAmQIAIfkBCACzAgAh-gEIALMCACENtgEAAL8CADC3AQAAkAEAELgBAAC_AgAwuQECAKkCACG-AUAArAIAIdsBAQCqAgAh9AEBAKoCACH1AQgAuQIAIfYBCAC5AgAh9wEBAKoCACH4AQEAqgIAIfkBCAC5AgAh-gEIALkCACEMtgEAAMACADC3AQAAigEAELgBAADAAgAwuQECAJgCACG-AUAAmwIAIdUBAQCZAgAh-wEBAJkCACH8AQEAmQIAIf0BAQCaAgAh_gEBAJkCACH_AUAAmwIAIYACAgCYAgAhDLYBAADBAgAwtwEAAHkAELgBAADBAgAwuQECAKkCACG-AUAArAIAIdUBAQCqAgAh-wEBAKoCACH8AQEAqgIAIf0BAQCrAgAh_gEBAKoCACH_AUAArAIAIYACAgCpAgAhAvsBAQAAAAH_AUAAAAABCbYBAADDAgAwtwEAAHMAELgBAADDAgAwuQECAJgCACG-AUAAmwIAIb8BQACbAgAh2wEBAJkCACGCAgIAmAIAIYMCCACzAgAhDbYBAADEAgAwtwEAAF8AELgBAADEAgAwuQECAJgCACG-AUAAmwIAIb8BQACbAgAh1AEBAJkCACH7AQEAmQIAIf4BAQCZAgAhhAIBAJkCACGFAgEAmQIAIYYCAQCZAgAhhwIgAMUCACEFEwAAoAIAIBYAAMcCACAXAADHAgAgwAEgAAAAAcsBIADGAgAhBRMAAKACACAWAADHAgAgFwAAxwIAIMABIAAAAAHLASAAxgIAIQLAASAAAAABywEgAMcCACEONwAAygIAILYBAADIAgAwtwEAAE4AELgBAADIAgAwuQECAKkCACG-AUAArAIAIb8BQACsAgAh1AEBAKoCACH7AQEAqgIAIf4BAQCqAgAhhAIBAKoCACGFAgEAqgIAIYYCAQCqAgAhhwIgAMkCACECwAEgAAAAAcsBIADHAgAhA4gCAABIACCJAgAASAAgigIAAEgAIALbAQEAAAABggICAAAAAQo2AADNAgAgtgEAAMwCADC3AQAASAAQuAEAAMwCADC5AQIAqQIAIb4BQACsAgAhvwFAAKwCACHbAQEAqgIAIYICAgCpAgAhgwIIALkCACEQNwAAygIAILYBAADIAgAwtwEAAE4AELgBAADIAgAwuQECAKkCACG-AUAArAIAIb8BQACsAgAh1AEBAKoCACH7AQEAqgIAIf4BAQCqAgAhhAIBAKoCACGFAgEAqgIAIYYCAQCqAgAhhwIgAMkCACGRAgAATgAgkgIAAE4AIAkIAADPAgAgtgEAAM4CADC3AQAAQwAQuAEAAM4CADC5AQIAmAIAIb4BQACbAgAhvwFAAJsCACHUAQEAmQIAIYwCAQCZAgAhDxMAAKACACAWAADQAgAgFwAA0AIAIMABgAAAAAHBAQEAAAABwgEBAAAAAcMBAQAAAAHEAYAAAAABxQGAAAAAAcYBgAAAAAHHAYAAAAAByAGAAAAAAckBgAAAAAHKAYAAAAABywGAAAAAAQzAAYAAAAABwQEBAAAAAcIBAQAAAAHDAQEAAAABxAGAAAAAAcUBgAAAAAHGAYAAAAABxwGAAAAAAcgBgAAAAAHJAYAAAAABygGAAAAAAcsBgAAAAAEJCAAA0gIAILYBAADRAgAwtwEAADIAELgBAADRAgAwuQECAKkCACG-AUAArAIAIb8BQACsAgAh1AEBAKoCACGMAgEAqgIAIQzAAYAAAAABwQEBAAAAAcIBAQAAAAHDAQEAAAABxAGAAAAAAcUBgAAAAAHGAYAAAAABxwGAAAAAAcgBgAAAAAHJAYAAAAABygGAAAAAAcsBgAAAAAEKtgEAANMCADC3AQAALAAQuAEAANMCADC5AQIAmAIAIb4BQACbAgAhvwFAAJsCACH7AQEAmQIAIf0BAQCZAgAhjQIBAJkCACGOAgEAmQIAIQq2AQAA1AIAMLcBAAAbABC4AQAA1AIAMLkBAgCpAgAhvgFAAKwCACG_AUAArAIAIfsBAQCqAgAh_QEBAKoCACGNAgEAqgIAIY4CAQCqAgAhCbYBAADVAgAwtwEAABUAELgBAADVAgAwuQECAJgCACG-AUAAmwIAIb8BQACbAgAh1AEBAJkCACGPAgEAmQIAIZACAQCZAgAhCbYBAADWAgAwtwEAAAQAELgBAADWAgAwuQECAKkCACG-AUAArAIAIb8BQACsAgAh1AEBAKoCACGPAgEAqgIAIZACAQCqAgAhAAAAAAAAAZcCAQAAAAEBlwIBAAAAAQGXAkAAAAABBZcCAgAAAAGdAgIAAAABngICAAAAAZ8CAgAAAAGgAgIAAAABAdEBAQAAAAEAAAAAAAHRAQEAAAABAAAAAAAB0QEBAAAAAQAAAAAABZcCCAAAAAGdAggAAAABngIIAAAAAZ8CCAAAAAGgAggAAAABBZcCBAAAAAGdAgQAAAABngIEAAAAAZ8CBAAAAAGgAgQAAAABAdEBAQAAAAEAAAAAAAHRAQEAAAABAAAAAAAB0QEBAAAAAQAAAAAAAdEBAQAAAAEAAAAAAAUNAAC6AwAgDgAAvQMAIJQCAAC7AwAglQIAALwDACCaAgAARgAgAw0AALoDACCUAgAAuwMAIJoCAABGACAAAAAAAAGXAiAAAAABCw0AAJYDADAOAACbAwAwlAIAAJcDADCVAgAAmAMAMJYCAACZAwAglwIAAJoDADCYAgAAmgMAMJkCAACaAwAwmgIAAJoDADCbAgAAnAMAMJwCAACdAwAwBbkBAgAAAAG-AUAAAAABvwFAAAAAAdsBAQAAAAGDAggAAAABAgAAAEoAIA0AAKEDACADAAAASgAgDQAAoQMAIA4AAKADACABCAAAuQMAMAs2AADNAgAgtgEAAMwCADC3AQAASAAQuAEAAMwCADC5AQIAAAABvgFAAKwCACG_AUAArAIAIdsBAQCqAgAhggICAKkCACGDAggAuQIAIYsCAADLAgAgAgAAAEoAIAgAAKADACACAAAAngMAIAgAAJ8DACAJtgEAAJ0DADC3AQAAngMAELgBAACdAwAwuQECAKkCACG-AUAArAIAIb8BQACsAgAh2wEBAKoCACGCAgIAqQIAIYMCCAC5AgAhCbYBAACdAwAwtwEAAJ4DABC4AQAAnQMAMLkBAgCpAgAhvgFAAKwCACG_AUAArAIAIdsBAQCqAgAhggICAKkCACGDAggAuQIAIQW5AQIA4AIAIb4BQADfAgAhvwFAAN8CACHbAQEA3QIAIYMCCADzAgAhBbkBAgDgAgAhvgFAAN8CACG_AUAA3wIAIdsBAQDdAgAhgwIIAPMCACEFuQECAAAAAb4BQAAAAAG_AUAAAAAB2wEBAAAAAYMCCAAAAAEEDQAAlgMAMJQCAACXAwAwlgIAAJkDACCaAgAAmgMAMAAB0QEBAAAAAQI3AACjAwAgkwIAAKQDACAB0QEBAAAAAQAAAAAAAdEBAQAAAAEAAAAAAAHRAQEAAAABAAAAAAAB0QEBAAAAAQW5AQIAAAABvgFAAAAAAb8BQAAAAAHbAQEAAAABgwIIAAAAAQq5AQIAAAABvgFAAAAAAb8BQAAAAAHUAQEAAAAB-wEBAAAAAf4BAQAAAAGEAgEAAAABhQIBAAAAAYYCAQAAAAGHAiAAAAABAgAAAEYAIA0AALoDACADAAAATgAgDQAAugMAIA4AAL4DACAMAAAATgAgCAAAvgMAILkBAgDgAgAhvgFAAN8CACG_AUAA3wIAIdQBAQDdAgAh-wEBAN0CACH-AQEA3QIAIYQCAQDdAgAhhQIBAN0CACGGAgEA3QIAIYcCIACUAwAhCrkBAgDgAgAhvgFAAN8CACG_AUAA3wIAIdQBAQDdAgAh-wEBAN0CACH-AQEA3QIAIYQCAQDdAgAhhQIBAN0CACGGAgEA3QIAIYcCIACUAwAhAAAFEwAEFAAFFQAGFgAHFwAIAAAAAAAFEwAEFAAFFQAGFgAHFwAIAAUTAAwUAA0VAA4WAA8XABAAAAAAAAUTAAwUAA0VAA4WAA8XABAABRMAFBQAFRUAFhYAFxcAGAAAAAAABRMAFBQAFRUAFhYAFxcAGAITABw3SxsBNgAaATdMAAUTAB4UAB8VACAWACEXACIAAAAAAAUTAB4UAB8VACAWACEXACIFEwAlFAAmFQAnFgAoFwApAAAAAAAFEwAlFAAmFQAnFgAoFwApAAUTAC0UAC4VAC8WADAXADEAAAAAAAUTAC0UAC4VAC8WADAXADEABRMANRQANhUANxYAOBcAOQAAAAAABRMANRQANhUANxYAOBcAOQAFEwA9FAA-FQA_FgBAFwBBAAAAAAAFEwA9FAA-FQA_FgBAFwBBAAUTAEUUAEYVAEcWAEgXAEkAAAAAAAUTAEUUAEYVAEcWAEgXAEkABRMATRQAThUATxYAUBcAUQAAAAAABRMATRQAThUATxYAUBcAUQAFEwBVFABWFQBXFgBYFwBZAAAAAAAFEwBVFABWFQBXFgBYFwBZAAUTAF0UAF4VAF8WAGAXAGEAAAAAAAUTAF0UAF4VAF8WAGAXAGEBAgECAwEFBgEGBwEHCAEJCgEKDAILDgEMEAIPEQEQEgEREwIYFgMZFwkaGQobGgocHQodHgoeHwofIQogIwIhJQoiJwIjKAokKQolKgImLQsnLhEoMBIpMRIqNBIrNRIsNhItOBIuOgIvPBIwPgIxPxIyQBIzQQI0RBM1RRk4Rxo5TRo6UBo7URo8Uho9VBo-VgI_WBpAWgJBWxpCXBpDXQJEYB1FYSNGYhtHYxtIZBtJZRtKZhtLaBtMagJNbBtObgJPbxtQcBtRcQJSdCRTdSpUdytVeCtWeytXfCtYfStZfytagQECW4MBK1yFAQJdhgErXocBK1-IAQJgiwEsYYwBMmKOATNjjwEzZJIBM2WTATNmlAEzZ5YBM2iYAQJpmgEzapwBAmudATNsngEzbZ8BAm6iATRvowE6cKUBO3GmATtyqQE7c6oBO3SrATt1rQE7dq8BAnexATt4swECebQBO3q1ATt7tgECfLkBPH26AUJ-vAFDf70BQ4ABwAFDgQHBAUOCAcIBQ4MBxAFDhAHGAQKFAcgBQ4YBygEChwHLAUOIAcwBQ4kBzQECigHQAUSLAdEBSowB0wFLjQHUAUuOAdcBS48B2AFLkAHZAUuRAdsBS5IB3QECkwHfAUuUAeEBApUB4gFLlgHjAUuXAeQBApgB5wFMmQHoAVKaAeoBU5sB6wFTnAHuAVOdAe8BU54B8AFTnwHyAVOgAfQBAqEB9gFTogH4AQKjAfkBU6QB-gFTpQH7AQKmAf4BVKcB_wFaqAGBAlupAYICW6oBhQJbqwGGAlusAYcCW60BiQJbrgGLAgKvAY0CW7ABjwICsQGQAluyAZECW7MBkgICtAGVAly1AZYCYg" + 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\",\"ServerNode.findUnique\",\"ServerNode.findUniqueOrThrow\",\"ServerNode.findFirst\",\"ServerNode.findFirstOrThrow\",\"ServerNode.findMany\",\"ServerNode.createOne\",\"ServerNode.createMany\",\"ServerNode.updateOne\",\"ServerNode.updateMany\",\"ServerNode.upsertOne\",\"ServerNode.deleteOne\",\"ServerNode.deleteMany\",\"ServerNode.groupBy\",\"ServerNode.aggregate\",\"ServerNodeHistory.findUnique\",\"ServerNodeHistory.findUniqueOrThrow\",\"ServerNodeHistory.findFirst\",\"ServerNodeHistory.findFirstOrThrow\",\"ServerNodeHistory.findMany\",\"ServerNodeHistory.createOne\",\"ServerNodeHistory.createMany\",\"ServerNodeHistory.updateOne\",\"ServerNodeHistory.updateMany\",\"ServerNodeHistory.upsertOne\",\"ServerNodeHistory.deleteOne\",\"ServerNodeHistory.deleteMany\",\"ServerNodeHistory.groupBy\",\"ServerNodeHistory.aggregate\",\"ServiceCheck.findUnique\",\"ServiceCheck.findUniqueOrThrow\",\"ServiceCheck.findFirst\",\"ServiceCheck.findFirstOrThrow\",\"ServiceCheck.findMany\",\"ServiceCheck.createOne\",\"ServiceCheck.createMany\",\"ServiceCheck.updateOne\",\"ServiceCheck.updateMany\",\"ServiceCheck.upsertOne\",\"ServiceCheck.deleteOne\",\"ServiceCheck.deleteMany\",\"ServiceCheck.groupBy\",\"ServiceCheck.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\",\"OilPriceHistory.findUnique\",\"OilPriceHistory.findUniqueOrThrow\",\"OilPriceHistory.findFirst\",\"OilPriceHistory.findFirstOrThrow\",\"OilPriceHistory.findMany\",\"OilPriceHistory.createOne\",\"OilPriceHistory.createMany\",\"OilPriceHistory.updateOne\",\"OilPriceHistory.updateMany\",\"OilPriceHistory.upsertOne\",\"OilPriceHistory.deleteOne\",\"OilPriceHistory.deleteMany\",\"OilPriceHistory.groupBy\",\"OilPriceHistory.aggregate\",\"AND\",\"OR\",\"NOT\",\"id\",\"date\",\"province\",\"fuel\",\"price\",\"source\",\"createdAt\",\"equals\",\"in\",\"notIn\",\"lt\",\"lte\",\"gt\",\"gte\",\"not\",\"contains\",\"startsWith\",\"endsWith\",\"search\",\"date_province_fuel\",\"scraperName\",\"lastDataHash\",\"lastUpdateAt\",\"metadata\",\"updatedAt\",\"string_contains\",\"string_starts_with\",\"string_ends_with\",\"array_starts_with\",\"array_ends_with\",\"array_contains\",\"month\",\"inventory\",\"name\",\"url\",\"status\",\"latencyMs\",\"message\",\"lastCheckAt\",\"uuid\",\"period\",\"cpu\",\"ram\",\"load\",\"disk\",\"netIn\",\"netOut\",\"process\",\"connections\",\"uuid_period\",\"cpuName\",\"os\",\"region\",\"memTotal\",\"diskTotal\",\"cpuCores\",\"cpuUsage\",\"ramUsed\",\"swapUsed\",\"load1\",\"load5\",\"load15\",\"diskUsed\",\"uptime\",\"recordedAt\",\"indicatorName\",\"valueA\",\"valueB\",\"sourceA\",\"sourceB\",\"diff\",\"diffRatio\",\"title\",\"summary\",\"content\",\"publishedAt\",\"impactRank\",\"title_publishedAt\",\"indicatorId\",\"value\",\"groupName\",\"unit\",\"frequency\",\"hidden\",\"every\",\"some\",\"none\",\"indicatorId_period\",\"description\",\"slug\",\"email\",\"password\",\"is\",\"isNot\",\"_relevance\",\"connectOrCreate\",\"upsert\",\"createMany\",\"set\",\"disconnect\",\"delete\",\"connect\",\"updateMany\",\"deleteMany\",\"increment\",\"decrement\",\"multiply\",\"divide\"]"), + graph: "3gNqtgEJxAEAAPACADDFAQAABAAQxgEAAPACADDHAQIAAAABzQFAAL0CACHfAUAAvQIAIegBAQC-AgAhoQIBAAAAAaICAQC-AgAhAQAAAAEAIAEAAAABACAJxAEAAPACADDFAQAABAAQxgEAAPACADDHAQIAvAIAIc0BQAC9AgAh3wFAAL0CACHoAQEAvgIAIaECAQC-AgAhogIBAL4CACEBpQIAANgDACADAAAABAAgAwAABQAwBAAAAQAgAwAAAAQAIAMAAAUAMAQAAAEAIAMAAAAEACADAAAFADAEAAABACAGxwECAAAAAc0BQAAAAAHfAUAAAAAB6AEBAAAAAaECAQAAAAGiAgEAAAABAQgAAAkAIAbHAQIAAAABzQFAAAAAAd8BQAAAAAHoAQEAAAABoQIBAAAAAaICAQAAAAEBCAAACwAwBscBAgD5AgAhzQFAAPYCACHfAUAA9gIAIegBAQD3AgAhoQIBAPcCACGiAgEA9wIAIQIAAAABACAIAAANACAGxwECAPkCACHNAUAA9gIAId8BQAD2AgAh6AEBAPcCACGhAgEA9wIAIaICAQD3AgAhAgAAAAQAIAgAAA8AIAMAAAABACANAAAJACAOAAANACABAAAAAQAgAQAAAAQAIAUTAADTAwAgFAAA1AMAIBUAANcDACAWAADWAwAgFwAA1QMAIAnEAQAA7wIAMMUBAAAVABDGAQAA7wIAMMcBAgCvAgAhzQFAALACACHfAUAAsAIAIegBAQCxAgAhoQIBALECACGiAgEAsQIAIQMAAAAEACADAAAUADASAAAVACADAAAABAAgAwAABQAwBAAAAQAgCsQBAADuAgAwxQEAABsAEMYBAADuAgAwxwECAAAAAcgBAQC-AgAhzQFAAL0CACHfAUAAvQIAIY8CAQC-AgAhkQIBAL4CACGgAgEAAAABAQAAABgAIAEAAAAYACAKxAEAAO4CADDFAQAAGwAQxgEAAO4CADDHAQIAvAIAIcgBAQC-AgAhzQFAAL0CACHfAUAAvQIAIY8CAQC-AgAhkQIBAL4CACGgAgEAvgIAIQGlAgAA0gMAIAMAAAAbACADAAAcADAEAAAYACADAAAAGwAgAwAAHAAwBAAAGAAgAwAAABsAIAMAABwAMAQAABgAIAfHAQIAAAAByAEBAAAAAc0BQAAAAAHfAUAAAAABjwIBAAAAAZECAQAAAAGgAgEAAAABAQgAACAAIAfHAQIAAAAByAEBAAAAAc0BQAAAAAHfAUAAAAABjwIBAAAAAZECAQAAAAGgAgEAAAABAQgAACIAMAfHAQIA-QIAIcgBAQD3AgAhzQFAAPYCACHfAUAA9gIAIY8CAQD3AgAhkQIBAPcCACGgAgEA9wIAIQIAAAAYACAIAAAkACAHxwECAPkCACHIAQEA9wIAIc0BQAD2AgAh3wFAAPYCACGPAgEA9wIAIZECAQD3AgAhoAIBAPcCACECAAAAGwAgCAAAJgAgAwAAABgAIA0AACAAIA4AACQAIAEAAAAYACABAAAAGwAgBRMAAM0DACAUAADOAwAgFQAA0QMAIBYAANADACAXAADPAwAgCsQBAADtAgAwxQEAACwAEMYBAADtAgAwxwECAK8CACHIAQEAsQIAIc0BQACwAgAh3wFAALACACGPAgEAsQIAIZECAQCxAgAhoAIBALECACEDAAAAGwAgAwAAKwAwEgAALAAgAwAAABsAIAMAABwAMAQAABgAIAkIAADsAgAgxAEAAOsCADDFAQAAMgAQxgEAAOsCADDHAQIAAAABzQFAAL0CACHfAUAAvQIAIegBAQC-AgAhnwIBAL4CACEBAAAALwAgAQAAAC8AIAkIAADsAgAgxAEAAOsCADDFAQAAMgAQxgEAAOsCADDHAQIAvAIAIc0BQAC9AgAh3wFAAL0CACHoAQEAvgIAIZ8CAQC-AgAhAaUCAADMAwAgAwAAADIAIAMAADMAMAQAAC8AIAMAAAAyACADAAAzADAEAAAvACADAAAAMgAgAwAAMwAwBAAALwAgBgiAAAAAAccBAgAAAAHNAUAAAAAB3wFAAAAAAegBAQAAAAGfAgEAAAABAQgAADcAIAYIgAAAAAHHAQIAAAABzQFAAAAAAd8BQAAAAAHoAQEAAAABnwIBAAAAAQEIAAA5ADAGCIAAAAABxwECAPkCACHNAUAA9gIAId8BQAD2AgAh6AEBAPcCACGfAgEA9wIAIQIAAAAvACAIAAA7ACAGCIAAAAABxwECAPkCACHNAUAA9gIAId8BQAD2AgAh6AEBAPcCACGfAgEA9wIAIQIAAAAyACAIAAA9ACADAAAALwAgDQAANwAgDgAAOwAgAQAAAC8AIAEAAAAyACAFEwAAxwMAIBQAAMgDACAVAADLAwAgFgAAygMAIBcAAMkDACAJCAAA6QIAIMQBAADoAgAwxQEAAEMAEMYBAADoAgAwxwECAK8CACHNAUAAsAIAId8BQACwAgAh6AEBALECACGfAgEAsQIAIQMAAAAyACADAABCADASAABDACADAAAAMgAgAwAAMwAwBAAALwAgDjcAAOQCACDEAQAA4gIAMMUBAABOABDGAQAA4gIAMMcBAgAAAAHMAQEAvgIAIc0BQAC9AgAh3wFAAL0CACHoAQEAAAABjwIBAL4CACGXAgEAvgIAIZgCAQC-AgAhmQIBAL4CACGaAiAA4wIAIQEAAABGACAKNgAA5wIAIMQBAADmAgAwxQEAAEgAEMYBAADmAgAwxwECALwCACHNAUAAvQIAId8BQAC9AgAh7wEBAL4CACGVAgIAvAIAIZYCCAC_AgAhAjYAAMUDACClAgAAxgMAIAs2AADnAgAgxAEAAOYCADDFAQAASAAQxgEAAOYCADDHAQIAAAABzQFAAL0CACHfAUAAvQIAIe8BAQC-AgAhlQICALwCACGWAggAvwIAIZ4CAADlAgAgAwAAAEgAIAMAAEkAMAQAAEoAIAEAAABIACABAAAARgAgDjcAAOQCACDEAQAA4gIAMMUBAABOABDGAQAA4gIAMMcBAgC8AgAhzAEBAL4CACHNAUAAvQIAId8BQAC9AgAh6AEBAL4CACGPAgEAvgIAIZcCAQC-AgAhmAIBAL4CACGZAgEAvgIAIZoCIADjAgAhAjcAAMMDACClAgAAxAMAIAMAAABOACADAABPADAEAABGACADAAAATgAgAwAATwAwBAAARgAgAwAAAE4AIAMAAE8AMAQAAEYAIAs3AADCAwAgxwECAAAAAcwBAQAAAAHNAUAAAAAB3wFAAAAAAegBAQAAAAGPAgEAAAABlwIBAAAAAZgCAQAAAAGZAgEAAAABmgIgAAAAAQEIAABTACAKxwECAAAAAcwBAQAAAAHNAUAAAAAB3wFAAAAAAegBAQAAAAGPAgEAAAABlwIBAAAAAZgCAQAAAAGZAgEAAAABmgIgAAAAAQEIAABVADALNwAAtQMAIMcBAgD5AgAhzAEBAPcCACHNAUAA9gIAId8BQAD2AgAh6AEBAPcCACGPAgEA9wIAIZcCAQD3AgAhmAIBAPcCACGZAgEA9wIAIZoCIAC0AwAhAgAAAEYAIAgAAFcAIArHAQIA-QIAIcwBAQD3AgAhzQFAAPYCACHfAUAA9gIAIegBAQD3AgAhjwIBAPcCACGXAgEA9wIAIZgCAQD3AgAhmQIBAPcCACGaAiAAtAMAIQIAAABOACAIAABZACADAAAARgAgDQAAUwAgDgAAVwAgAQAAAEYAIAEAAABOACAFEwAArwMAIBQAALADACAVAACzAwAgFgAAsgMAIBcAALEDACANxAEAAN4CADDFAQAAXwAQxgEAAN4CADDHAQIArwIAIcwBAQCxAgAhzQFAALACACHfAUAAsAIAIegBAQCxAgAhjwIBALECACGXAgEAsQIAIZgCAQCxAgAhmQIBALECACGaAiAA3wIAIQMAAABOACADAABeADASAABfACADAAAATgAgAwAATwAwBAAARgAgAQAAAEoAIAEAAABKACADAAAASAAgAwAASQAwBAAASgAgAwAAAEgAIAMAAEkAMAQAAEoAIAMAAABIACADAABJADAEAABKACAHNgAArgMAIMcBAgAAAAHNAUAAAAAB3wFAAAAAAe8BAQAAAAGVAgIAAAABlgIIAAAAAQEIAABnACAGxwECAAAAAc0BQAAAAAHfAUAAAAAB7wEBAAAAAZUCAgAAAAGWAggAAAABAQgAAGkAMAc2AACtAwAgxwECAPkCACHNAUAA9gIAId8BQAD2AgAh7wEBAPcCACGVAgIA-QIAIZYCCAD4AgAhAgAAAEoAIAgAAGsAIAbHAQIA-QIAIc0BQAD2AgAh3wFAAPYCACHvAQEA9wIAIZUCAgD5AgAhlgIIAPgCACECAAAASAAgCAAAbQAgAwAAAEoAIA0AAGcAIA4AAGsAIAEAAABKACABAAAASAAgBRMAAKgDACAUAACpAwAgFQAArAMAIBYAAKsDACAXAACqAwAgCcQBAADdAgAwxQEAAHMAEMYBAADdAgAwxwECAK8CACHNAUAAsAIAId8BQACwAgAh7wEBALECACGVAgIArwIAIZYCCACyAgAhAwAAAEgAIAMAAHIAMBIAAHMAIAMAAABIACADAABJADAEAABKACANxAEAANsCADDFAQAAeQAQxgEAANsCADDHAQIAAAABzAEBAL4CACHNAUAAvQIAIekBAQC-AgAhjwIBAL4CACGQAgEAvgIAIZECAQDJAgAhkgJAAL0CACGTAgIAvAIAIZQCAADcAgAgAQAAAHYAIAEAAAB2ACAMxAEAANsCADDFAQAAeQAQxgEAANsCADDHAQIAvAIAIcwBAQC-AgAhzQFAAL0CACHpAQEAvgIAIY8CAQC-AgAhkAIBAL4CACGRAgEAyQIAIZICQAC9AgAhkwICALwCACECkQIAAPsCACClAgAApwMAIAMAAAB5ACADAAB6ADAEAAB2ACADAAAAeQAgAwAAegAwBAAAdgAgAwAAAHkAIAMAAHoAMAQAAHYAIAnHAQIAAAABzAEBAAAAAc0BQAAAAAHpAQEAAAABjwIBAAAAAZACAQAAAAGRAgEAAAABkgJAAAAAAZMCAgAAAAEBCAAAfgAgCccBAgAAAAHMAQEAAAABzQFAAAAAAekBAQAAAAGPAgEAAAABkAIBAAAAAZECAQAAAAGSAkAAAAABkwICAAAAAQEIAACAAQAwCccBAgD5AgAhzAEBAPcCACHNAUAA9gIAIekBAQD3AgAhjwIBAPcCACGQAgEA9wIAIZECAQCBAwAhkgJAAPYCACGTAgIA-QIAIQIAAAB2ACAIAACCAQAgCccBAgD5AgAhzAEBAPcCACHNAUAA9gIAIekBAQD3AgAhjwIBAPcCACGQAgEA9wIAIZECAQCBAwAhkgJAAPYCACGTAgIA-QIAIQIAAAB5ACAIAACEAQAgAwAAAHYAIA0AAH4AIA4AAIIBACABAAAAdgAgAQAAAHkAIAYTAACiAwAgFAAAowMAIBUAAKYDACAWAAClAwAgFwAApAMAIJECAAD7AgAgDMQBAADaAgAwxQEAAIoBABDGAQAA2gIAMMcBAgCvAgAhzAEBALECACHNAUAAsAIAIekBAQCxAgAhjwIBALECACGQAgEAsQIAIZECAQDCAgAhkgJAALACACGTAgIArwIAIQMAAAB5ACADAACJAQAwEgAAigEAIAMAAAB5ACADAAB6ADAEAAB2ACANxAEAANkCADDFAQAAkAEAEMYBAADZAgAwxwECAAAAAc0BQAC9AgAh7wEBAL4CACGIAgEAvgIAIYkCCAC_AgAhigIIAL8CACGLAgEAvgIAIYwCAQC-AgAhjQIIAL8CACGOAggAvwIAIQEAAACNAQAgAQAAAI0BACANxAEAANkCADDFAQAAkAEAEMYBAADZAgAwxwECALwCACHNAUAAvQIAIe8BAQC-AgAhiAIBAL4CACGJAggAvwIAIYoCCAC_AgAhiwIBAL4CACGMAgEAvgIAIY0CCAC_AgAhjgIIAL8CACEBpQIAAKEDACADAAAAkAEAIAMAAJEBADAEAACNAQAgAwAAAJABACADAACRAQAwBAAAjQEAIAMAAACQAQAgAwAAkQEAMAQAAI0BACAKxwECAAAAAc0BQAAAAAHvAQEAAAABiAIBAAAAAYkCCAAAAAGKAggAAAABiwIBAAAAAYwCAQAAAAGNAggAAAABjgIIAAAAAQEIAACVAQAgCscBAgAAAAHNAUAAAAAB7wEBAAAAAYgCAQAAAAGJAggAAAABigIIAAAAAYsCAQAAAAGMAgEAAAABjQIIAAAAAY4CCAAAAAEBCAAAlwEAMArHAQIA-QIAIc0BQAD2AgAh7wEBAPcCACGIAgEA9wIAIYkCCAD4AgAhigIIAPgCACGLAgEA9wIAIYwCAQD3AgAhjQIIAPgCACGOAggA-AIAIQIAAACNAQAgCAAAmQEAIArHAQIA-QIAIc0BQAD2AgAh7wEBAPcCACGIAgEA9wIAIYkCCAD4AgAhigIIAPgCACGLAgEA9wIAIYwCAQD3AgAhjQIIAPgCACGOAggA-AIAIQIAAACQAQAgCAAAmwEAIAMAAACNAQAgDQAAlQEAIA4AAJkBACABAAAAjQEAIAEAAACQAQAgBRMAAJwDACAUAACdAwAgFQAAoAMAIBYAAJ8DACAXAACeAwAgDcQBAADYAgAwxQEAAKEBABDGAQAA2AIAMMcBAgCvAgAhzQFAALACACHvAQEAsQIAIYgCAQCxAgAhiQIIALICACGKAggAsgIAIYsCAQCxAgAhjAIBALECACGNAggAsgIAIY4CCACyAgAhAwAAAJABACADAACgAQAwEgAAoQEAIAMAAACQAQAgAwAAkQEAMAQAAI0BACAcxAEAANcCADDFAQAApwEAEMYBAADXAgAwxwECAAAAAc0BQAC9AgAh3wFAAL0CACHoAQEAvgIAIeoBAQC-AgAh7gEBAAAAAfQBBADUAgAh9QEEANQCACH2AQIAvAIAIfcBAgC8AgAh-QEBAL4CACH6AQEAvgIAIfsBAQC-AgAh_AEEANQCACH9AQQA1AIAIf4BAgC8AgAh_wEIAL8CACGAAgQA1AIAIYECBADUAgAhggIIAL8CACGDAggAvwIAIYQCCAC_AgAhhQIEANQCACGGAgQA1AIAIYcCQAC9AgAhAQAAAKQBACABAAAApAEAIBzEAQAA1wIAMMUBAACnAQAQxgEAANcCADDHAQIAvAIAIc0BQAC9AgAh3wFAAL0CACHoAQEAvgIAIeoBAQC-AgAh7gEBAL4CACH0AQQA1AIAIfUBBADUAgAh9gECALwCACH3AQIAvAIAIfkBAQC-AgAh-gEBAL4CACH7AQEAvgIAIfwBBADUAgAh_QEEANQCACH-AQIAvAIAIf8BCAC_AgAhgAIEANQCACGBAgQA1AIAIYICCAC_AgAhgwIIAL8CACGEAggAvwIAIYUCBADUAgAhhgIEANQCACGHAkAAvQIAIQGlAgAAmwMAIAMAAACnAQAgAwAAqAEAMAQAAKQBACADAAAApwEAIAMAAKgBADAEAACkAQAgAwAAAKcBACADAACoAQAwBAAApAEAIBnHAQIAAAABzQFAAAAAAd8BQAAAAAHoAQEAAAAB6gEBAAAAAe4BAQAAAAH0AQQAAAAB9QEEAAAAAfYBAgAAAAH3AQIAAAAB-QEBAAAAAfoBAQAAAAH7AQEAAAAB_AEEAAAAAf0BBAAAAAH-AQIAAAAB_wEIAAAAAYACBAAAAAGBAgQAAAABggIIAAAAAYMCCAAAAAGEAggAAAABhQIEAAAAAYYCBAAAAAGHAkAAAAABAQgAAKwBACAZxwECAAAAAc0BQAAAAAHfAUAAAAAB6AEBAAAAAeoBAQAAAAHuAQEAAAAB9AEEAAAAAfUBBAAAAAH2AQIAAAAB9wECAAAAAfkBAQAAAAH6AQEAAAAB-wEBAAAAAfwBBAAAAAH9AQQAAAAB_gECAAAAAf8BCAAAAAGAAgQAAAABgQIEAAAAAYICCAAAAAGDAggAAAABhAIIAAAAAYUCBAAAAAGGAgQAAAABhwJAAAAAAQEIAACuAQAwGccBAgD5AgAhzQFAAPYCACHfAUAA9gIAIegBAQD3AgAh6gEBAPcCACHuAQEA9wIAIfQBBACUAwAh9QEEAJQDACH2AQIA-QIAIfcBAgD5AgAh-QEBAPcCACH6AQEA9wIAIfsBAQD3AgAh_AEEAJQDACH9AQQAlAMAIf4BAgD5AgAh_wEIAPgCACGAAgQAlAMAIYECBACUAwAhggIIAPgCACGDAggA-AIAIYQCCAD4AgAhhQIEAJQDACGGAgQAlAMAIYcCQAD2AgAhAgAAAKQBACAIAACwAQAgGccBAgD5AgAhzQFAAPYCACHfAUAA9gIAIegBAQD3AgAh6gEBAPcCACHuAQEA9wIAIfQBBACUAwAh9QEEAJQDACH2AQIA-QIAIfcBAgD5AgAh-QEBAPcCACH6AQEA9wIAIfsBAQD3AgAh_AEEAJQDACH9AQQAlAMAIf4BAgD5AgAh_wEIAPgCACGAAgQAlAMAIYECBACUAwAhggIIAPgCACGDAggA-AIAIYQCCAD4AgAhhQIEAJQDACGGAgQAlAMAIYcCQAD2AgAhAgAAAKcBACAIAACyAQAgAwAAAKQBACANAACsAQAgDgAAsAEAIAEAAACkAQAgAQAAAKcBACAFEwAAlgMAIBQAAJcDACAVAACaAwAgFgAAmQMAIBcAAJgDACAcxAEAANYCADDFAQAAuAEAEMYBAADWAgAwxwECAK8CACHNAUAAsAIAId8BQACwAgAh6AEBALECACHqAQEAsQIAIe4BAQCxAgAh9AEEANACACH1AQQA0AIAIfYBAgCvAgAh9wECAK8CACH5AQEAsQIAIfoBAQCxAgAh-wEBALECACH8AQQA0AIAIf0BBADQAgAh_gECAK8CACH_AQgAsgIAIYACBADQAgAhgQIEANACACGCAggAsgIAIYMCCACyAgAhhAIIALICACGFAgQA0AIAIYYCBADQAgAhhwJAALACACEDAAAApwEAIAMAALcBADASAAC4AQAgAwAAAKcBACADAACoAQAwBAAApAEAIBDEAQAA0wIAMMUBAAC-AQAQxgEAANMCADDHAQIAAAABzQFAAL0CACHuAQEAvgIAIe8BQAC9AgAh8AEIAL8CACHxAQQA1AIAIfIBCAC_AgAh8wEEANQCACH0AQQA1AIAIfUBBADUAgAh9gECALwCACH3AQIAvAIAIfgBAADVAgAgAQAAALsBACABAAAAuwEAIA_EAQAA0wIAMMUBAAC-AQAQxgEAANMCADDHAQIAvAIAIc0BQAC9AgAh7gEBAL4CACHvAUAAvQIAIfABCAC_AgAh8QEEANQCACHyAQgAvwIAIfMBBADUAgAh9AEEANQCACH1AQQA1AIAIfYBAgC8AgAh9wECALwCACEBpQIAAJUDACADAAAAvgEAIAMAAL8BADAEAAC7AQAgAwAAAL4BACADAAC_AQAwBAAAuwEAIAMAAAC-AQAgAwAAvwEAMAQAALsBACAMxwECAAAAAc0BQAAAAAHuAQEAAAAB7wFAAAAAAfABCAAAAAHxAQQAAAAB8gEIAAAAAfMBBAAAAAH0AQQAAAAB9QEEAAAAAfYBAgAAAAH3AQIAAAABAQgAAMMBACAMxwECAAAAAc0BQAAAAAHuAQEAAAAB7wFAAAAAAfABCAAAAAHxAQQAAAAB8gEIAAAAAfMBBAAAAAH0AQQAAAAB9QEEAAAAAfYBAgAAAAH3AQIAAAABAQgAAMUBADAMxwECAPkCACHNAUAA9gIAIe4BAQD3AgAh7wFAAPYCACHwAQgA-AIAIfEBBACUAwAh8gEIAPgCACHzAQQAlAMAIfQBBACUAwAh9QEEAJQDACH2AQIA-QIAIfcBAgD5AgAhAgAAALsBACAIAADHAQAgDMcBAgD5AgAhzQFAAPYCACHuAQEA9wIAIe8BQAD2AgAh8AEIAPgCACHxAQQAlAMAIfIBCAD4AgAh8wEEAJQDACH0AQQAlAMAIfUBBACUAwAh9gECAPkCACH3AQIA-QIAIQIAAAC-AQAgCAAAyQEAIAMAAAC7AQAgDQAAwwEAIA4AAMcBACABAAAAuwEAIAEAAAC-AQAgBRMAAI8DACAUAACQAwAgFQAAkwMAIBYAAJIDACAXAACRAwAgD8QBAADPAgAwxQEAAM8BABDGAQAAzwIAMMcBAgCvAgAhzQFAALACACHuAQEAsQIAIe8BQACwAgAh8AEIALICACHxAQQA0AIAIfIBCACyAgAh8wEEANACACH0AQQA0AIAIfUBBADQAgAh9gECAK8CACH3AQIArwIAIQMAAAC-AQAgAwAAzgEAMBIAAM8BACADAAAAvgEAIAMAAL8BADAEAAC7AQAgDMQBAADOAgAwxQEAANUBABDGAQAAzgIAMMcBAgAAAAHNAUAAvQIAId8BQAC9AgAh6AEBAAAAAekBAQC-AgAh6gEBAL4CACHrAQIAvAIAIewBAQC-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-AgAg3AEAAPsCACDeAQAA-wIAIArEAQAAwQIAMMUBAACUAgAQxgEAAMECADDHAQIArwIAIc0BQACwAgAh2wEBALECACHcAQEAwgIAId0BQACwAgAh3gEAAMMCACDfAUAAsAIAIQMAAACDAgAgAwAAkwIAMBIAAJQCACADAAAAgwIAIAMAAIQCADAEAACAAgAgC8QBAAC7AgAwxQEAAJoCABDGAQAAuwIAMMcBAgAAAAHIAUAAvQIAIckBAQC-AgAhygEBAL4CACHLAQgAvwIAIcwBAQC-AgAhzQFAAL0CACHaAQAAwAIAIAEAAACXAgAgAQAAAJcCACAKxAEAALsCADDFAQAAmgIAEMYBAAC7AgAwxwECALwCACHIAUAAvQIAIckBAQC-AgAhygEBAL4CACHLAQgAvwIAIcwBAQC-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_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_EAQAAzwIAMMUBAADPAQAQxgEAAM8CADDHAQIArwIAIc0BQACwAgAh7gEBALECACHvAUAAsAIAIfABCACyAgAh8QEEANACACHyAQgAsgIAIfMBBADQAgAh9AEEANACACH1AQQA0AIAIfYBAgCvAgAh9wECAK8CACENEwAAtAIAIBQAALUCACAVAADSAgAgFgAA0gIAIBcAANICACDOAQQAAAABzwEEAAAABNABBAAAAATRAQQAAAAB0gEEAAAAAdMBBAAAAAHUAQQAAAAB1QEEANECACENEwAAtAIAIBQAALUCACAVAADSAgAgFgAA0gIAIBcAANICACDOAQQAAAABzwEEAAAABNABBAAAAATRAQQAAAAB0gEEAAAAAdMBBAAAAAHUAQQAAAAB1QEEANECACEIzgEEAAAAAc8BBAAAAATQAQQAAAAE0QEEAAAAAdIBBAAAAAHTAQQAAAAB1AEEAAAAAdUBBADSAgAhD8QBAADTAgAwxQEAAL4BABDGAQAA0wIAMMcBAgC8AgAhzQFAAL0CACHuAQEAvgIAIe8BQAC9AgAh8AEIAL8CACHxAQQA1AIAIfIBCAC_AgAh8wEEANQCACH0AQQA1AIAIfUBBADUAgAh9gECALwCACH3AQIAvAIAIQjOAQQAAAABzwEEAAAABNABBAAAAATRAQQAAAAB0gEEAAAAAdMBBAAAAAHUAQQAAAAB1QEEANICACEC7gEBAAAAAe8BQAAAAAEcxAEAANYCADDFAQAAuAEAEMYBAADWAgAwxwECAK8CACHNAUAAsAIAId8BQACwAgAh6AEBALECACHqAQEAsQIAIe4BAQCxAgAh9AEEANACACH1AQQA0AIAIfYBAgCvAgAh9wECAK8CACH5AQEAsQIAIfoBAQCxAgAh-wEBALECACH8AQQA0AIAIf0BBADQAgAh_gECAK8CACH_AQgAsgIAIYACBADQAgAhgQIEANACACGCAggAsgIAIYMCCACyAgAhhAIIALICACGFAgQA0AIAIYYCBADQAgAhhwJAALACACEcxAEAANcCADDFAQAApwEAEMYBAADXAgAwxwECALwCACHNAUAAvQIAId8BQAC9AgAh6AEBAL4CACHqAQEAvgIAIe4BAQC-AgAh9AEEANQCACH1AQQA1AIAIfYBAgC8AgAh9wECALwCACH5AQEAvgIAIfoBAQC-AgAh-wEBAL4CACH8AQQA1AIAIf0BBADUAgAh_gECALwCACH_AQgAvwIAIYACBADUAgAhgQIEANQCACGCAggAvwIAIYMCCAC_AgAhhAIIAL8CACGFAgQA1AIAIYYCBADUAgAhhwJAAL0CACENxAEAANgCADDFAQAAoQEAEMYBAADYAgAwxwECAK8CACHNAUAAsAIAIe8BAQCxAgAhiAIBALECACGJAggAsgIAIYoCCACyAgAhiwIBALECACGMAgEAsQIAIY0CCACyAgAhjgIIALICACENxAEAANkCADDFAQAAkAEAEMYBAADZAgAwxwECALwCACHNAUAAvQIAIe8BAQC-AgAhiAIBAL4CACGJAggAvwIAIYoCCAC_AgAhiwIBAL4CACGMAgEAvgIAIY0CCAC_AgAhjgIIAL8CACEMxAEAANoCADDFAQAAigEAEMYBAADaAgAwxwECAK8CACHMAQEAsQIAIc0BQACwAgAh6QEBALECACGPAgEAsQIAIZACAQCxAgAhkQIBAMICACGSAkAAsAIAIZMCAgCvAgAhDMQBAADbAgAwxQEAAHkAEMYBAADbAgAwxwECALwCACHMAQEAvgIAIc0BQAC9AgAh6QEBAL4CACGPAgEAvgIAIZACAQC-AgAhkQIBAMkCACGSAkAAvQIAIZMCAgC8AgAhAo8CAQAAAAGSAkAAAAABCcQBAADdAgAwxQEAAHMAEMYBAADdAgAwxwECAK8CACHNAUAAsAIAId8BQACwAgAh7wEBALECACGVAgIArwIAIZYCCACyAgAhDcQBAADeAgAwxQEAAF8AEMYBAADeAgAwxwECAK8CACHMAQEAsQIAIc0BQACwAgAh3wFAALACACHoAQEAsQIAIY8CAQCxAgAhlwIBALECACGYAgEAsQIAIZkCAQCxAgAhmgIgAN8CACEFEwAAtAIAIBYAAOECACAXAADhAgAgzgEgAAAAAdUBIADgAgAhBRMAALQCACAWAADhAgAgFwAA4QIAIM4BIAAAAAHVASAA4AIAIQLOASAAAAAB1QEgAOECACEONwAA5AIAIMQBAADiAgAwxQEAAE4AEMYBAADiAgAwxwECALwCACHMAQEAvgIAIc0BQAC9AgAh3wFAAL0CACHoAQEAvgIAIY8CAQC-AgAhlwIBAL4CACGYAgEAvgIAIZkCAQC-AgAhmgIgAOMCACECzgEgAAAAAdUBIADhAgAhA5sCAABIACCcAgAASAAgnQIAAEgAIALvAQEAAAABlQICAAAAAQo2AADnAgAgxAEAAOYCADDFAQAASAAQxgEAAOYCADDHAQIAvAIAIc0BQAC9AgAh3wFAAL0CACHvAQEAvgIAIZUCAgC8AgAhlgIIAL8CACEQNwAA5AIAIMQBAADiAgAwxQEAAE4AEMYBAADiAgAwxwECALwCACHMAQEAvgIAIc0BQAC9AgAh3wFAAL0CACHoAQEAvgIAIY8CAQC-AgAhlwIBAL4CACGYAgEAvgIAIZkCAQC-AgAhmgIgAOMCACGjAgAATgAgpAIAAE4AIAkIAADpAgAgxAEAAOgCADDFAQAAQwAQxgEAAOgCADDHAQIArwIAIc0BQACwAgAh3wFAALACACHoAQEAsQIAIZ8CAQCxAgAhDxMAALQCACAWAADqAgAgFwAA6gIAIM4BgAAAAAHRAYAAAAAB0gGAAAAAAdMBgAAAAAHUAYAAAAAB1QGAAAAAAeABAQAAAAHhAQEAAAAB4gEBAAAAAeMBgAAAAAHkAYAAAAAB5QGAAAAAAQzOAYAAAAAB0QGAAAAAAdIBgAAAAAHTAYAAAAAB1AGAAAAAAdUBgAAAAAHgAQEAAAAB4QEBAAAAAeIBAQAAAAHjAYAAAAAB5AGAAAAAAeUBgAAAAAEJCAAA7AIAIMQBAADrAgAwxQEAADIAEMYBAADrAgAwxwECALwCACHNAUAAvQIAId8BQAC9AgAh6AEBAL4CACGfAgEAvgIAIQzOAYAAAAAB0QGAAAAAAdIBgAAAAAHTAYAAAAAB1AGAAAAAAdUBgAAAAAHgAQEAAAAB4QEBAAAAAeIBAQAAAAHjAYAAAAAB5AGAAAAAAeUBgAAAAAEKxAEAAO0CADDFAQAALAAQxgEAAO0CADDHAQIArwIAIcgBAQCxAgAhzQFAALACACHfAUAAsAIAIY8CAQCxAgAhkQIBALECACGgAgEAsQIAIQrEAQAA7gIAMMUBAAAbABDGAQAA7gIAMMcBAgC8AgAhyAEBAL4CACHNAUAAvQIAId8BQAC9AgAhjwIBAL4CACGRAgEAvgIAIaACAQC-AgAhCcQBAADvAgAwxQEAABUAEMYBAADvAgAwxwECAK8CACHNAUAAsAIAId8BQACwAgAh6AEBALECACGhAgEAsQIAIaICAQCxAgAhCcQBAADwAgAwxQEAAAQAEMYBAADwAgAwxwECALwCACHNAUAAvQIAId8BQAC9AgAh6AEBAL4CACGhAgEAvgIAIaICAQC-AgAhAAAAAAABqQJAAAAAAQGpAgEAAAABBakCCAAAAAGvAggAAAABsAIIAAAAAbECCAAAAAGyAggAAAABBakCAgAAAAGvAgIAAAABsAICAAAAAbECAgAAAAGyAgIAAAABAdkBAQAAAAEAAAAAAAABqQIBAAAAAQHZAQEAAAABAAAAAAAB2QEBAAAAAQAAAAAAAdkBAQAAAAEAAAAAAAWpAgQAAAABrwIEAAAAAbACBAAAAAGxAgQAAAABsgIEAAAAAQHZAQEAAAABAAAAAAAB2QEBAAAAAQAAAAAAAdkBAQAAAAEAAAAAAAHZAQEAAAABAAAAAAAFDQAA2gMAIA4AAN0DACCmAgAA2wMAIKcCAADcAwAgrAIAAEYAIAMNAADaAwAgpgIAANsDACCsAgAARgAgAAAAAAABqQIgAAAAAQsNAAC2AwAwDgAAuwMAMKYCAAC3AwAwpwIAALgDADCoAgAAuQMAIKkCAAC6AwAwqgIAALoDADCrAgAAugMAMKwCAAC6AwAwrQIAALwDADCuAgAAvQMAMAXHAQIAAAABzQFAAAAAAd8BQAAAAAHvAQEAAAABlgIIAAAAAQIAAABKACANAADBAwAgAwAAAEoAIA0AAMEDACAOAADAAwAgAQgAANkDADALNgAA5wIAIMQBAADmAgAwxQEAAEgAEMYBAADmAgAwxwECAAAAAc0BQAC9AgAh3wFAAL0CACHvAQEAvgIAIZUCAgC8AgAhlgIIAL8CACGeAgAA5QIAIAIAAABKACAIAADAAwAgAgAAAL4DACAIAAC_AwAgCcQBAAC9AwAwxQEAAL4DABDGAQAAvQMAMMcBAgC8AgAhzQFAAL0CACHfAUAAvQIAIe8BAQC-AgAhlQICALwCACGWAggAvwIAIQnEAQAAvQMAMMUBAAC-AwAQxgEAAL0DADDHAQIAvAIAIc0BQAC9AgAh3wFAAL0CACHvAQEAvgIAIZUCAgC8AgAhlgIIAL8CACEFxwECAPkCACHNAUAA9gIAId8BQAD2AgAh7wEBAPcCACGWAggA-AIAIQXHAQIA-QIAIc0BQAD2AgAh3wFAAPYCACHvAQEA9wIAIZYCCAD4AgAhBccBAgAAAAHNAUAAAAAB3wFAAAAAAe8BAQAAAAGWAggAAAABBA0AALYDADCmAgAAtwMAMKgCAAC5AwAgrAIAALoDADAAAdkBAQAAAAECNwAAwwMAIKUCAADEAwAgAdkBAQAAAAEAAAAAAAHZAQEAAAABAAAAAAAB2QEBAAAAAQAAAAAAAdkBAQAAAAEFxwECAAAAAc0BQAAAAAHfAUAAAAAB7wEBAAAAAZYCCAAAAAEKxwECAAAAAcwBAQAAAAHNAUAAAAAB3wFAAAAAAegBAQAAAAGPAgEAAAABlwIBAAAAAZgCAQAAAAGZAgEAAAABmgIgAAAAAQIAAABGACANAADaAwAgAwAAAE4AIA0AANoDACAOAADeAwAgDAAAAE4AIAgAAN4DACDHAQIA-QIAIcwBAQD3AgAhzQFAAPYCACHfAUAA9gIAIegBAQD3AgAhjwIBAPcCACGXAgEA9wIAIZgCAQD3AgAhmQIBAPcCACGaAiAAtAMAIQrHAQIA-QIAIcwBAQD3AgAhzQFAAPYCACHfAUAA9gIAIegBAQD3AgAhjwIBAPcCACGXAgEA9wIAIZgCAQD3AgAhmQIBAPcCACGaAiAAtAMAIQAABRMABBQABRUABhYABxcACAAAAAAABRMABBQABRUABhYABxcACAAFEwAMFAANFQAOFgAPFwAQAAAAAAAFEwAMFAANFQAOFgAPFwAQAAUTABQUABUVABYWABcXABgAAAAAAAUTABQUABUVABYWABcXABgCEwAcN0sbATYAGgE3TAAFEwAeFAAfFQAgFgAhFwAiAAAAAAAFEwAeFAAfFQAgFgAhFwAiBRMAJRQAJhUAJxYAKBcAKQAAAAAABRMAJRQAJhUAJxYAKBcAKQAFEwAtFAAuFQAvFgAwFwAxAAAAAAAFEwAtFAAuFQAvFgAwFwAxAAUTADUUADYVADcWADgXADkAAAAAAAUTADUUADYVADcWADgXADkABRMAPRQAPhUAPxYAQBcAQQAAAAAABRMAPRQAPhUAPxYAQBcAQQAFEwBFFABGFQBHFgBIFwBJAAAAAAAFEwBFFABGFQBHFgBIFwBJAAUTAE0UAE4VAE8WAFAXAFEAAAAAAAUTAE0UAE4VAE8WAFAXAFEABRMAVRQAVhUAVxYAWBcAWQAAAAAABRMAVRQAVhUAVxYAWBcAWQAFEwBdFABeFQBfFgBgFwBhAAAAAAAFEwBdFABeFQBfFgBgFwBhAAUTAGUUAGYVAGcWAGgXAGkAAAAAAAUTAGUUAGYVAGcWAGgXAGkBAgECAwEFBgEGBwEHCAEJCgEKDAILDgEMEAIPEQEQEgEREwIYFgMZFwkaGQobGgocHQodHgoeHwofIQogIwIhJQoiJwIjKAokKQolKgImLQsnLhEoMBIpMRIqNBIrNRIsNhItOBIuOgIvPBIwPgIxPxIyQBIzQQI0RBM1RRk4Rxo5TRo6UBo7URo8Uho9VBo-VgI_WBpAWgJBWxpCXBpDXQJEYB1FYSNGYhtHYxtIZBtJZRtKZhtLaBtMagJNbBtObgJPbxtQcBtRcQJSdCRTdSpUdytVeCtWeytXfCtYfStZfytagQECW4MBK1yFAQJdhgErXocBK1-IAQJgiwEsYYwBMmKOATNjjwEzZJIBM2WTATNmlAEzZ5YBM2iYAQJpmgEzapwBAmudATNsngEzbZ8BAm6iATRvowE6cKUBO3GmATtyqQE7c6oBO3SrATt1rQE7dq8BAnexATt4swECebQBO3q1ATt7tgECfLkBPH26AUJ-vAFDf70BQ4ABwAFDgQHBAUOCAcIBQ4MBxAFDhAHGAQKFAcgBQ4YBygEChwHLAUOIAcwBQ4kBzQECigHQAUSLAdEBSowB0wFLjQHUAUuOAdcBS48B2AFLkAHZAUuRAdsBS5IB3QECkwHfAUuUAeEBApUB4gFLlgHjAUuXAeQBApgB5wFMmQHoAVKaAeoBU5sB6wFTnAHuAVOdAe8BU54B8AFTnwHyAVOgAfQBAqEB9gFTogH4AQKjAfkBU6QB-gFTpQH7AQKmAf4BVKcB_wFaqAGBAlupAYICW6oBhQJbqwGGAlusAYcCW60BiQJbrgGLAgKvAY0CW7ABjwICsQGQAluyAZECW7MBkgICtAGVAly1AZYCYrYBmAJjtwGZAmO4AZwCY7kBnQJjugGeAmO7AaACY7wBogICvQGkAmO-AaYCAr8BpwJjwAGoAmPBAakCAsIBrAJkwwGtAmo" } async function decodeBase64AsWasm(wasmBase64: string): Promise { @@ -307,6 +307,16 @@ export interface PrismaClient< * ``` */ get scraperCache(): Prisma.ScraperCacheDelegate; + + /** + * `prisma.oilPriceHistory`: Exposes CRUD operations for the **OilPriceHistory** model. + * Example usage: + * ```ts + * // Fetch zero or more OilPriceHistories + * const oilPriceHistories = await prisma.oilPriceHistory.findMany() + * ``` + */ + get oilPriceHistory(): Prisma.OilPriceHistoryDelegate; } export function getPrismaClientClass(): PrismaClientConstructor { diff --git a/generated/prisma/internal/prismaNamespace.ts b/generated/prisma/internal/prismaNamespace.ts index 314f1dc..61326f2 100644 --- a/generated/prisma/internal/prismaNamespace.ts +++ b/generated/prisma/internal/prismaNamespace.ts @@ -395,7 +395,8 @@ export const ModelName = { ServerNodeHistory: 'ServerNodeHistory', ServiceCheck: 'ServiceCheck', Econ_SowInventory: 'Econ_SowInventory', - ScraperCache: 'ScraperCache' + ScraperCache: 'ScraperCache', + OilPriceHistory: 'OilPriceHistory' } as const export type ModelName = (typeof ModelName)[keyof typeof ModelName] @@ -411,7 +412,7 @@ export type TypeMap + fields: Prisma.OilPriceHistoryFieldRefs + operations: { + findUnique: { + args: Prisma.OilPriceHistoryFindUniqueArgs + result: runtime.Types.Utils.PayloadToResult | null + } + findUniqueOrThrow: { + args: Prisma.OilPriceHistoryFindUniqueOrThrowArgs + result: runtime.Types.Utils.PayloadToResult + } + findFirst: { + args: Prisma.OilPriceHistoryFindFirstArgs + result: runtime.Types.Utils.PayloadToResult | null + } + findFirstOrThrow: { + args: Prisma.OilPriceHistoryFindFirstOrThrowArgs + result: runtime.Types.Utils.PayloadToResult + } + findMany: { + args: Prisma.OilPriceHistoryFindManyArgs + result: runtime.Types.Utils.PayloadToResult[] + } + create: { + args: Prisma.OilPriceHistoryCreateArgs + result: runtime.Types.Utils.PayloadToResult + } + createMany: { + args: Prisma.OilPriceHistoryCreateManyArgs + result: BatchPayload + } + delete: { + args: Prisma.OilPriceHistoryDeleteArgs + result: runtime.Types.Utils.PayloadToResult + } + update: { + args: Prisma.OilPriceHistoryUpdateArgs + result: runtime.Types.Utils.PayloadToResult + } + deleteMany: { + args: Prisma.OilPriceHistoryDeleteManyArgs + result: BatchPayload + } + updateMany: { + args: Prisma.OilPriceHistoryUpdateManyArgs + result: BatchPayload + } + upsert: { + args: Prisma.OilPriceHistoryUpsertArgs + result: runtime.Types.Utils.PayloadToResult + } + aggregate: { + args: Prisma.OilPriceHistoryAggregateArgs + result: runtime.Types.Utils.Optional + } + groupBy: { + args: Prisma.OilPriceHistoryGroupByArgs + result: runtime.Types.Utils.Optional[] + } + count: { + args: Prisma.OilPriceHistoryCountArgs + result: runtime.Types.Utils.Optional | number + } + } + } } } & { other: { @@ -1430,6 +1497,19 @@ export const ScraperCacheScalarFieldEnum = { export type ScraperCacheScalarFieldEnum = (typeof ScraperCacheScalarFieldEnum)[keyof typeof ScraperCacheScalarFieldEnum] +export const OilPriceHistoryScalarFieldEnum = { + id: 'id', + date: 'date', + province: 'province', + fuel: 'fuel', + price: 'price', + source: 'source', + createdAt: 'createdAt' +} as const + +export type OilPriceHistoryScalarFieldEnum = (typeof OilPriceHistoryScalarFieldEnum)[keyof typeof OilPriceHistoryScalarFieldEnum] + + export const SortOrder = { asc: 'asc', desc: 'desc' @@ -1589,6 +1669,15 @@ export const ScraperCacheOrderByRelevanceFieldEnum = { export type ScraperCacheOrderByRelevanceFieldEnum = (typeof ScraperCacheOrderByRelevanceFieldEnum)[keyof typeof ScraperCacheOrderByRelevanceFieldEnum] +export const OilPriceHistoryOrderByRelevanceFieldEnum = { + province: 'province', + fuel: 'fuel', + source: 'source' +} as const + +export type OilPriceHistoryOrderByRelevanceFieldEnum = (typeof OilPriceHistoryOrderByRelevanceFieldEnum)[keyof typeof OilPriceHistoryOrderByRelevanceFieldEnum] + + /** * Field references @@ -1757,6 +1846,7 @@ export type GlobalOmitConfig = { serviceCheck?: Prisma.ServiceCheckOmit econ_SowInventory?: Prisma.Econ_SowInventoryOmit scraperCache?: Prisma.ScraperCacheOmit + oilPriceHistory?: Prisma.OilPriceHistoryOmit } /* Types for Logging */ diff --git a/generated/prisma/internal/prismaNamespaceBrowser.ts b/generated/prisma/internal/prismaNamespaceBrowser.ts index d7a51ac..957cf8e 100644 --- a/generated/prisma/internal/prismaNamespaceBrowser.ts +++ b/generated/prisma/internal/prismaNamespaceBrowser.ts @@ -62,7 +62,8 @@ export const ModelName = { ServerNodeHistory: 'ServerNodeHistory', ServiceCheck: 'ServiceCheck', Econ_SowInventory: 'Econ_SowInventory', - ScraperCache: 'ScraperCache' + ScraperCache: 'ScraperCache', + OilPriceHistory: 'OilPriceHistory' } as const export type ModelName = (typeof ModelName)[keyof typeof ModelName] @@ -265,6 +266,19 @@ export const ScraperCacheScalarFieldEnum = { export type ScraperCacheScalarFieldEnum = (typeof ScraperCacheScalarFieldEnum)[keyof typeof ScraperCacheScalarFieldEnum] +export const OilPriceHistoryScalarFieldEnum = { + id: 'id', + date: 'date', + province: 'province', + fuel: 'fuel', + price: 'price', + source: 'source', + createdAt: 'createdAt' +} as const + +export type OilPriceHistoryScalarFieldEnum = (typeof OilPriceHistoryScalarFieldEnum)[keyof typeof OilPriceHistoryScalarFieldEnum] + + export const SortOrder = { asc: 'asc', desc: 'desc' @@ -423,3 +437,12 @@ export const ScraperCacheOrderByRelevanceFieldEnum = { export type ScraperCacheOrderByRelevanceFieldEnum = (typeof ScraperCacheOrderByRelevanceFieldEnum)[keyof typeof ScraperCacheOrderByRelevanceFieldEnum] + +export const OilPriceHistoryOrderByRelevanceFieldEnum = { + province: 'province', + fuel: 'fuel', + source: 'source' +} as const + +export type OilPriceHistoryOrderByRelevanceFieldEnum = (typeof OilPriceHistoryOrderByRelevanceFieldEnum)[keyof typeof OilPriceHistoryOrderByRelevanceFieldEnum] + diff --git a/generated/prisma/models.ts b/generated/prisma/models.ts index 54302c0..2396f9c 100644 --- a/generated/prisma/models.ts +++ b/generated/prisma/models.ts @@ -20,4 +20,5 @@ export type * from './models/ServerNodeHistory.ts' export type * from './models/ServiceCheck.ts' export type * from './models/Econ_SowInventory.ts' export type * from './models/ScraperCache.ts' +export type * from './models/OilPriceHistory.ts' export type * from './commonInputTypes.ts' \ No newline at end of file diff --git a/generated/prisma/models/OilPriceHistory.ts b/generated/prisma/models/OilPriceHistory.ts new file mode 100644 index 0000000..0a2c329 --- /dev/null +++ b/generated/prisma/models/OilPriceHistory.ts @@ -0,0 +1,1149 @@ + +/* !!! This is code generated by Prisma. Do not edit directly. !!! */ +/* eslint-disable */ +// biome-ignore-all lint: generated file +// @ts-nocheck +/* + * This file exports the `OilPriceHistory` 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 OilPriceHistory + * + */ +export type OilPriceHistoryModel = runtime.Types.Result.DefaultSelection + +export type AggregateOilPriceHistory = { + _count: OilPriceHistoryCountAggregateOutputType | null + _avg: OilPriceHistoryAvgAggregateOutputType | null + _sum: OilPriceHistorySumAggregateOutputType | null + _min: OilPriceHistoryMinAggregateOutputType | null + _max: OilPriceHistoryMaxAggregateOutputType | null +} + +export type OilPriceHistoryAvgAggregateOutputType = { + id: number | null + price: number | null +} + +export type OilPriceHistorySumAggregateOutputType = { + id: number | null + price: number | null +} + +export type OilPriceHistoryMinAggregateOutputType = { + id: number | null + date: Date | null + province: string | null + fuel: string | null + price: number | null + source: string | null + createdAt: Date | null +} + +export type OilPriceHistoryMaxAggregateOutputType = { + id: number | null + date: Date | null + province: string | null + fuel: string | null + price: number | null + source: string | null + createdAt: Date | null +} + +export type OilPriceHistoryCountAggregateOutputType = { + id: number + date: number + province: number + fuel: number + price: number + source: number + createdAt: number + _all: number +} + + +export type OilPriceHistoryAvgAggregateInputType = { + id?: true + price?: true +} + +export type OilPriceHistorySumAggregateInputType = { + id?: true + price?: true +} + +export type OilPriceHistoryMinAggregateInputType = { + id?: true + date?: true + province?: true + fuel?: true + price?: true + source?: true + createdAt?: true +} + +export type OilPriceHistoryMaxAggregateInputType = { + id?: true + date?: true + province?: true + fuel?: true + price?: true + source?: true + createdAt?: true +} + +export type OilPriceHistoryCountAggregateInputType = { + id?: true + date?: true + province?: true + fuel?: true + price?: true + source?: true + createdAt?: true + _all?: true +} + +export type OilPriceHistoryAggregateArgs = { + /** + * Filter which OilPriceHistory to aggregate. + */ + where?: Prisma.OilPriceHistoryWhereInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/sorting Sorting Docs} + * + * Determine the order of OilPriceHistories to fetch. + */ + orderBy?: Prisma.OilPriceHistoryOrderByWithRelationInput | Prisma.OilPriceHistoryOrderByWithRelationInput[] + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination#cursor-based-pagination Cursor Docs} + * + * Sets the start position + */ + cursor?: Prisma.OilPriceHistoryWhereUniqueInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Take `±n` OilPriceHistories 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` OilPriceHistories. + */ + skip?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Count returned OilPriceHistories + **/ + _count?: true | OilPriceHistoryCountAggregateInputType + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Select which fields to average + **/ + _avg?: OilPriceHistoryAvgAggregateInputType + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Select which fields to sum + **/ + _sum?: OilPriceHistorySumAggregateInputType + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Select which fields to find the minimum value + **/ + _min?: OilPriceHistoryMinAggregateInputType + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Select which fields to find the maximum value + **/ + _max?: OilPriceHistoryMaxAggregateInputType +} + +export type GetOilPriceHistoryAggregateType = { + [P in keyof T & keyof AggregateOilPriceHistory]: P extends '_count' | 'count' + ? T[P] extends true + ? number + : Prisma.GetScalarType + : Prisma.GetScalarType +} + + + + +export type OilPriceHistoryGroupByArgs = { + where?: Prisma.OilPriceHistoryWhereInput + orderBy?: Prisma.OilPriceHistoryOrderByWithAggregationInput | Prisma.OilPriceHistoryOrderByWithAggregationInput[] + by: Prisma.OilPriceHistoryScalarFieldEnum[] | Prisma.OilPriceHistoryScalarFieldEnum + having?: Prisma.OilPriceHistoryScalarWhereWithAggregatesInput + take?: number + skip?: number + _count?: OilPriceHistoryCountAggregateInputType | true + _avg?: OilPriceHistoryAvgAggregateInputType + _sum?: OilPriceHistorySumAggregateInputType + _min?: OilPriceHistoryMinAggregateInputType + _max?: OilPriceHistoryMaxAggregateInputType +} + +export type OilPriceHistoryGroupByOutputType = { + id: number + date: Date + province: string + fuel: string + price: number + source: string + createdAt: Date + _count: OilPriceHistoryCountAggregateOutputType | null + _avg: OilPriceHistoryAvgAggregateOutputType | null + _sum: OilPriceHistorySumAggregateOutputType | null + _min: OilPriceHistoryMinAggregateOutputType | null + _max: OilPriceHistoryMaxAggregateOutputType | null +} + +export type GetOilPriceHistoryGroupByPayload = Prisma.PrismaPromise< + Array< + Prisma.PickEnumerable & + { + [P in ((keyof T) & (keyof OilPriceHistoryGroupByOutputType))]: P extends '_count' + ? T[P] extends boolean + ? number + : Prisma.GetScalarType + : Prisma.GetScalarType + } + > + > + + + +export type OilPriceHistoryWhereInput = { + AND?: Prisma.OilPriceHistoryWhereInput | Prisma.OilPriceHistoryWhereInput[] + OR?: Prisma.OilPriceHistoryWhereInput[] + NOT?: Prisma.OilPriceHistoryWhereInput | Prisma.OilPriceHistoryWhereInput[] + id?: Prisma.IntFilter<"OilPriceHistory"> | number + date?: Prisma.DateTimeFilter<"OilPriceHistory"> | Date | string + province?: Prisma.StringFilter<"OilPriceHistory"> | string + fuel?: Prisma.StringFilter<"OilPriceHistory"> | string + price?: Prisma.FloatFilter<"OilPriceHistory"> | number + source?: Prisma.StringFilter<"OilPriceHistory"> | string + createdAt?: Prisma.DateTimeFilter<"OilPriceHistory"> | Date | string +} + +export type OilPriceHistoryOrderByWithRelationInput = { + id?: Prisma.SortOrder + date?: Prisma.SortOrder + province?: Prisma.SortOrder + fuel?: Prisma.SortOrder + price?: Prisma.SortOrder + source?: Prisma.SortOrder + createdAt?: Prisma.SortOrder + _relevance?: Prisma.OilPriceHistoryOrderByRelevanceInput +} + +export type OilPriceHistoryWhereUniqueInput = Prisma.AtLeast<{ + id?: number + date_province_fuel?: Prisma.OilPriceHistoryDateProvinceFuelCompoundUniqueInput + AND?: Prisma.OilPriceHistoryWhereInput | Prisma.OilPriceHistoryWhereInput[] + OR?: Prisma.OilPriceHistoryWhereInput[] + NOT?: Prisma.OilPriceHistoryWhereInput | Prisma.OilPriceHistoryWhereInput[] + date?: Prisma.DateTimeFilter<"OilPriceHistory"> | Date | string + province?: Prisma.StringFilter<"OilPriceHistory"> | string + fuel?: Prisma.StringFilter<"OilPriceHistory"> | string + price?: Prisma.FloatFilter<"OilPriceHistory"> | number + source?: Prisma.StringFilter<"OilPriceHistory"> | string + createdAt?: Prisma.DateTimeFilter<"OilPriceHistory"> | Date | string +}, "id" | "date_province_fuel"> + +export type OilPriceHistoryOrderByWithAggregationInput = { + id?: Prisma.SortOrder + date?: Prisma.SortOrder + province?: Prisma.SortOrder + fuel?: Prisma.SortOrder + price?: Prisma.SortOrder + source?: Prisma.SortOrder + createdAt?: Prisma.SortOrder + _count?: Prisma.OilPriceHistoryCountOrderByAggregateInput + _avg?: Prisma.OilPriceHistoryAvgOrderByAggregateInput + _max?: Prisma.OilPriceHistoryMaxOrderByAggregateInput + _min?: Prisma.OilPriceHistoryMinOrderByAggregateInput + _sum?: Prisma.OilPriceHistorySumOrderByAggregateInput +} + +export type OilPriceHistoryScalarWhereWithAggregatesInput = { + AND?: Prisma.OilPriceHistoryScalarWhereWithAggregatesInput | Prisma.OilPriceHistoryScalarWhereWithAggregatesInput[] + OR?: Prisma.OilPriceHistoryScalarWhereWithAggregatesInput[] + NOT?: Prisma.OilPriceHistoryScalarWhereWithAggregatesInput | Prisma.OilPriceHistoryScalarWhereWithAggregatesInput[] + id?: Prisma.IntWithAggregatesFilter<"OilPriceHistory"> | number + date?: Prisma.DateTimeWithAggregatesFilter<"OilPriceHistory"> | Date | string + province?: Prisma.StringWithAggregatesFilter<"OilPriceHistory"> | string + fuel?: Prisma.StringWithAggregatesFilter<"OilPriceHistory"> | string + price?: Prisma.FloatWithAggregatesFilter<"OilPriceHistory"> | number + source?: Prisma.StringWithAggregatesFilter<"OilPriceHistory"> | string + createdAt?: Prisma.DateTimeWithAggregatesFilter<"OilPriceHistory"> | Date | string +} + +export type OilPriceHistoryCreateInput = { + date: Date | string + province: string + fuel: string + price: number + source?: string + createdAt?: Date | string +} + +export type OilPriceHistoryUncheckedCreateInput = { + id?: number + date: Date | string + province: string + fuel: string + price: number + source?: string + createdAt?: Date | string +} + +export type OilPriceHistoryUpdateInput = { + date?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + province?: Prisma.StringFieldUpdateOperationsInput | string + fuel?: Prisma.StringFieldUpdateOperationsInput | string + price?: Prisma.FloatFieldUpdateOperationsInput | number + source?: Prisma.StringFieldUpdateOperationsInput | string + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string +} + +export type OilPriceHistoryUncheckedUpdateInput = { + id?: Prisma.IntFieldUpdateOperationsInput | number + date?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + province?: Prisma.StringFieldUpdateOperationsInput | string + fuel?: Prisma.StringFieldUpdateOperationsInput | string + price?: Prisma.FloatFieldUpdateOperationsInput | number + source?: Prisma.StringFieldUpdateOperationsInput | string + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string +} + +export type OilPriceHistoryCreateManyInput = { + id?: number + date: Date | string + province: string + fuel: string + price: number + source?: string + createdAt?: Date | string +} + +export type OilPriceHistoryUpdateManyMutationInput = { + date?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + province?: Prisma.StringFieldUpdateOperationsInput | string + fuel?: Prisma.StringFieldUpdateOperationsInput | string + price?: Prisma.FloatFieldUpdateOperationsInput | number + source?: Prisma.StringFieldUpdateOperationsInput | string + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string +} + +export type OilPriceHistoryUncheckedUpdateManyInput = { + id?: Prisma.IntFieldUpdateOperationsInput | number + date?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + province?: Prisma.StringFieldUpdateOperationsInput | string + fuel?: Prisma.StringFieldUpdateOperationsInput | string + price?: Prisma.FloatFieldUpdateOperationsInput | number + source?: Prisma.StringFieldUpdateOperationsInput | string + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string +} + +export type OilPriceHistoryOrderByRelevanceInput = { + fields: Prisma.OilPriceHistoryOrderByRelevanceFieldEnum | Prisma.OilPriceHistoryOrderByRelevanceFieldEnum[] + sort: Prisma.SortOrder + search: string +} + +export type OilPriceHistoryDateProvinceFuelCompoundUniqueInput = { + date: Date | string + province: string + fuel: string +} + +export type OilPriceHistoryCountOrderByAggregateInput = { + id?: Prisma.SortOrder + date?: Prisma.SortOrder + province?: Prisma.SortOrder + fuel?: Prisma.SortOrder + price?: Prisma.SortOrder + source?: Prisma.SortOrder + createdAt?: Prisma.SortOrder +} + +export type OilPriceHistoryAvgOrderByAggregateInput = { + id?: Prisma.SortOrder + price?: Prisma.SortOrder +} + +export type OilPriceHistoryMaxOrderByAggregateInput = { + id?: Prisma.SortOrder + date?: Prisma.SortOrder + province?: Prisma.SortOrder + fuel?: Prisma.SortOrder + price?: Prisma.SortOrder + source?: Prisma.SortOrder + createdAt?: Prisma.SortOrder +} + +export type OilPriceHistoryMinOrderByAggregateInput = { + id?: Prisma.SortOrder + date?: Prisma.SortOrder + province?: Prisma.SortOrder + fuel?: Prisma.SortOrder + price?: Prisma.SortOrder + source?: Prisma.SortOrder + createdAt?: Prisma.SortOrder +} + +export type OilPriceHistorySumOrderByAggregateInput = { + id?: Prisma.SortOrder + price?: Prisma.SortOrder +} + + + +export type OilPriceHistorySelect = runtime.Types.Extensions.GetSelect<{ + id?: boolean + date?: boolean + province?: boolean + fuel?: boolean + price?: boolean + source?: boolean + createdAt?: boolean +}, ExtArgs["result"]["oilPriceHistory"]> + + + +export type OilPriceHistorySelectScalar = { + id?: boolean + date?: boolean + province?: boolean + fuel?: boolean + price?: boolean + source?: boolean + createdAt?: boolean +} + +export type OilPriceHistoryOmit = runtime.Types.Extensions.GetOmit<"id" | "date" | "province" | "fuel" | "price" | "source" | "createdAt", ExtArgs["result"]["oilPriceHistory"]> + +export type $OilPriceHistoryPayload = { + name: "OilPriceHistory" + objects: {} + scalars: runtime.Types.Extensions.GetPayloadResult<{ + id: number + date: Date + province: string + fuel: string + price: number + source: string + createdAt: Date + }, ExtArgs["result"]["oilPriceHistory"]> + composites: {} +} + +export type OilPriceHistoryGetPayload = runtime.Types.Result.GetResult + +export type OilPriceHistoryCountArgs = + Omit & { + select?: OilPriceHistoryCountAggregateInputType | true + } + +export interface OilPriceHistoryDelegate { + [K: symbol]: { types: Prisma.TypeMap['model']['OilPriceHistory'], meta: { name: 'OilPriceHistory' } } + /** + * Find zero or one OilPriceHistory that matches the filter. + * @param {OilPriceHistoryFindUniqueArgs} args - Arguments to find a OilPriceHistory + * @example + * // Get one OilPriceHistory + * const oilPriceHistory = await prisma.oilPriceHistory.findUnique({ + * where: { + * // ... provide filter here + * } + * }) + */ + findUnique(args: Prisma.SelectSubset>): Prisma.Prisma__OilPriceHistoryClient, T, "findUnique", GlobalOmitOptions> | null, null, ExtArgs, GlobalOmitOptions> + + /** + * Find one OilPriceHistory that matches the filter or throw an error with `error.code='P2025'` + * if no matches were found. + * @param {OilPriceHistoryFindUniqueOrThrowArgs} args - Arguments to find a OilPriceHistory + * @example + * // Get one OilPriceHistory + * const oilPriceHistory = await prisma.oilPriceHistory.findUniqueOrThrow({ + * where: { + * // ... provide filter here + * } + * }) + */ + findUniqueOrThrow(args: Prisma.SelectSubset>): Prisma.Prisma__OilPriceHistoryClient, T, "findUniqueOrThrow", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + /** + * Find the first OilPriceHistory 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 {OilPriceHistoryFindFirstArgs} args - Arguments to find a OilPriceHistory + * @example + * // Get one OilPriceHistory + * const oilPriceHistory = await prisma.oilPriceHistory.findFirst({ + * where: { + * // ... provide filter here + * } + * }) + */ + findFirst(args?: Prisma.SelectSubset>): Prisma.Prisma__OilPriceHistoryClient, T, "findFirst", GlobalOmitOptions> | null, null, ExtArgs, GlobalOmitOptions> + + /** + * Find the first OilPriceHistory 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 {OilPriceHistoryFindFirstOrThrowArgs} args - Arguments to find a OilPriceHistory + * @example + * // Get one OilPriceHistory + * const oilPriceHistory = await prisma.oilPriceHistory.findFirstOrThrow({ + * where: { + * // ... provide filter here + * } + * }) + */ + findFirstOrThrow(args?: Prisma.SelectSubset>): Prisma.Prisma__OilPriceHistoryClient, T, "findFirstOrThrow", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + /** + * Find zero or more OilPriceHistories 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 {OilPriceHistoryFindManyArgs} args - Arguments to filter and select certain fields only. + * @example + * // Get all OilPriceHistories + * const oilPriceHistories = await prisma.oilPriceHistory.findMany() + * + * // Get first 10 OilPriceHistories + * const oilPriceHistories = await prisma.oilPriceHistory.findMany({ take: 10 }) + * + * // Only select the `id` + * const oilPriceHistoryWithIdOnly = await prisma.oilPriceHistory.findMany({ select: { id: true } }) + * + */ + findMany(args?: Prisma.SelectSubset>): Prisma.PrismaPromise, T, "findMany", GlobalOmitOptions>> + + /** + * Create a OilPriceHistory. + * @param {OilPriceHistoryCreateArgs} args - Arguments to create a OilPriceHistory. + * @example + * // Create one OilPriceHistory + * const OilPriceHistory = await prisma.oilPriceHistory.create({ + * data: { + * // ... data to create a OilPriceHistory + * } + * }) + * + */ + create(args: Prisma.SelectSubset>): Prisma.Prisma__OilPriceHistoryClient, T, "create", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + /** + * Create many OilPriceHistories. + * @param {OilPriceHistoryCreateManyArgs} args - Arguments to create many OilPriceHistories. + * @example + * // Create many OilPriceHistories + * const oilPriceHistory = await prisma.oilPriceHistory.createMany({ + * data: [ + * // ... provide data here + * ] + * }) + * + */ + createMany(args?: Prisma.SelectSubset>): Prisma.PrismaPromise + + /** + * Delete a OilPriceHistory. + * @param {OilPriceHistoryDeleteArgs} args - Arguments to delete one OilPriceHistory. + * @example + * // Delete one OilPriceHistory + * const OilPriceHistory = await prisma.oilPriceHistory.delete({ + * where: { + * // ... filter to delete one OilPriceHistory + * } + * }) + * + */ + delete(args: Prisma.SelectSubset>): Prisma.Prisma__OilPriceHistoryClient, T, "delete", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + /** + * Update one OilPriceHistory. + * @param {OilPriceHistoryUpdateArgs} args - Arguments to update one OilPriceHistory. + * @example + * // Update one OilPriceHistory + * const oilPriceHistory = await prisma.oilPriceHistory.update({ + * where: { + * // ... provide filter here + * }, + * data: { + * // ... provide data here + * } + * }) + * + */ + update(args: Prisma.SelectSubset>): Prisma.Prisma__OilPriceHistoryClient, T, "update", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + /** + * Delete zero or more OilPriceHistories. + * @param {OilPriceHistoryDeleteManyArgs} args - Arguments to filter OilPriceHistories to delete. + * @example + * // Delete a few OilPriceHistories + * const { count } = await prisma.oilPriceHistory.deleteMany({ + * where: { + * // ... provide filter here + * } + * }) + * + */ + deleteMany(args?: Prisma.SelectSubset>): Prisma.PrismaPromise + + /** + * Update zero or more OilPriceHistories. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {OilPriceHistoryUpdateManyArgs} args - Arguments to update one or more rows. + * @example + * // Update many OilPriceHistories + * const oilPriceHistory = await prisma.oilPriceHistory.updateMany({ + * where: { + * // ... provide filter here + * }, + * data: { + * // ... provide data here + * } + * }) + * + */ + updateMany(args: Prisma.SelectSubset>): Prisma.PrismaPromise + + /** + * Create or update one OilPriceHistory. + * @param {OilPriceHistoryUpsertArgs} args - Arguments to update or create a OilPriceHistory. + * @example + * // Update or create a OilPriceHistory + * const oilPriceHistory = await prisma.oilPriceHistory.upsert({ + * create: { + * // ... data to create a OilPriceHistory + * }, + * update: { + * // ... in case it already exists, update + * }, + * where: { + * // ... the filter for the OilPriceHistory we want to update + * } + * }) + */ + upsert(args: Prisma.SelectSubset>): Prisma.Prisma__OilPriceHistoryClient, T, "upsert", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + + /** + * Count the number of OilPriceHistories. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {OilPriceHistoryCountArgs} args - Arguments to filter OilPriceHistories to count. + * @example + * // Count the number of OilPriceHistories + * const count = await prisma.oilPriceHistory.count({ + * where: { + * // ... the filter for the OilPriceHistories 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 OilPriceHistory. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {OilPriceHistoryAggregateArgs} 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 OilPriceHistory. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {OilPriceHistoryGroupByArgs} 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 OilPriceHistoryGroupByArgs, + HasSelectOrTake extends Prisma.Or< + Prisma.Extends<'skip', Prisma.Keys>, + Prisma.Extends<'take', Prisma.Keys> + >, + OrderByArg extends Prisma.True extends HasSelectOrTake + ? { orderBy: OilPriceHistoryGroupByArgs['orderBy'] } + : { orderBy?: OilPriceHistoryGroupByArgs['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 ? GetOilPriceHistoryGroupByPayload : Prisma.PrismaPromise +/** + * Fields of the OilPriceHistory model + */ +readonly fields: OilPriceHistoryFieldRefs; +} + +/** + * The delegate class that acts as a "Promise-like" for OilPriceHistory. + * 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__OilPriceHistoryClient 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 OilPriceHistory model + */ +export interface OilPriceHistoryFieldRefs { + readonly id: Prisma.FieldRef<"OilPriceHistory", 'Int'> + readonly date: Prisma.FieldRef<"OilPriceHistory", 'DateTime'> + readonly province: Prisma.FieldRef<"OilPriceHistory", 'String'> + readonly fuel: Prisma.FieldRef<"OilPriceHistory", 'String'> + readonly price: Prisma.FieldRef<"OilPriceHistory", 'Float'> + readonly source: Prisma.FieldRef<"OilPriceHistory", 'String'> + readonly createdAt: Prisma.FieldRef<"OilPriceHistory", 'DateTime'> +} + + +// Custom InputTypes +/** + * OilPriceHistory findUnique + */ +export type OilPriceHistoryFindUniqueArgs = { + /** + * Select specific fields to fetch from the OilPriceHistory + */ + select?: Prisma.OilPriceHistorySelect | null + /** + * Omit specific fields from the OilPriceHistory + */ + omit?: Prisma.OilPriceHistoryOmit | null + /** + * Filter, which OilPriceHistory to fetch. + */ + where: Prisma.OilPriceHistoryWhereUniqueInput +} + +/** + * OilPriceHistory findUniqueOrThrow + */ +export type OilPriceHistoryFindUniqueOrThrowArgs = { + /** + * Select specific fields to fetch from the OilPriceHistory + */ + select?: Prisma.OilPriceHistorySelect | null + /** + * Omit specific fields from the OilPriceHistory + */ + omit?: Prisma.OilPriceHistoryOmit | null + /** + * Filter, which OilPriceHistory to fetch. + */ + where: Prisma.OilPriceHistoryWhereUniqueInput +} + +/** + * OilPriceHistory findFirst + */ +export type OilPriceHistoryFindFirstArgs = { + /** + * Select specific fields to fetch from the OilPriceHistory + */ + select?: Prisma.OilPriceHistorySelect | null + /** + * Omit specific fields from the OilPriceHistory + */ + omit?: Prisma.OilPriceHistoryOmit | null + /** + * Filter, which OilPriceHistory to fetch. + */ + where?: Prisma.OilPriceHistoryWhereInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/sorting Sorting Docs} + * + * Determine the order of OilPriceHistories to fetch. + */ + orderBy?: Prisma.OilPriceHistoryOrderByWithRelationInput | Prisma.OilPriceHistoryOrderByWithRelationInput[] + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination#cursor-based-pagination Cursor Docs} + * + * Sets the position for searching for OilPriceHistories. + */ + cursor?: Prisma.OilPriceHistoryWhereUniqueInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Take `±n` OilPriceHistories 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` OilPriceHistories. + */ + skip?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/distinct Distinct Docs} + * + * Filter by unique combinations of OilPriceHistories. + */ + distinct?: Prisma.OilPriceHistoryScalarFieldEnum | Prisma.OilPriceHistoryScalarFieldEnum[] +} + +/** + * OilPriceHistory findFirstOrThrow + */ +export type OilPriceHistoryFindFirstOrThrowArgs = { + /** + * Select specific fields to fetch from the OilPriceHistory + */ + select?: Prisma.OilPriceHistorySelect | null + /** + * Omit specific fields from the OilPriceHistory + */ + omit?: Prisma.OilPriceHistoryOmit | null + /** + * Filter, which OilPriceHistory to fetch. + */ + where?: Prisma.OilPriceHistoryWhereInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/sorting Sorting Docs} + * + * Determine the order of OilPriceHistories to fetch. + */ + orderBy?: Prisma.OilPriceHistoryOrderByWithRelationInput | Prisma.OilPriceHistoryOrderByWithRelationInput[] + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination#cursor-based-pagination Cursor Docs} + * + * Sets the position for searching for OilPriceHistories. + */ + cursor?: Prisma.OilPriceHistoryWhereUniqueInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Take `±n` OilPriceHistories 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` OilPriceHistories. + */ + skip?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/distinct Distinct Docs} + * + * Filter by unique combinations of OilPriceHistories. + */ + distinct?: Prisma.OilPriceHistoryScalarFieldEnum | Prisma.OilPriceHistoryScalarFieldEnum[] +} + +/** + * OilPriceHistory findMany + */ +export type OilPriceHistoryFindManyArgs = { + /** + * Select specific fields to fetch from the OilPriceHistory + */ + select?: Prisma.OilPriceHistorySelect | null + /** + * Omit specific fields from the OilPriceHistory + */ + omit?: Prisma.OilPriceHistoryOmit | null + /** + * Filter, which OilPriceHistories to fetch. + */ + where?: Prisma.OilPriceHistoryWhereInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/sorting Sorting Docs} + * + * Determine the order of OilPriceHistories to fetch. + */ + orderBy?: Prisma.OilPriceHistoryOrderByWithRelationInput | Prisma.OilPriceHistoryOrderByWithRelationInput[] + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination#cursor-based-pagination Cursor Docs} + * + * Sets the position for listing OilPriceHistories. + */ + cursor?: Prisma.OilPriceHistoryWhereUniqueInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Take `±n` OilPriceHistories 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` OilPriceHistories. + */ + skip?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/distinct Distinct Docs} + * + * Filter by unique combinations of OilPriceHistories. + */ + distinct?: Prisma.OilPriceHistoryScalarFieldEnum | Prisma.OilPriceHistoryScalarFieldEnum[] +} + +/** + * OilPriceHistory create + */ +export type OilPriceHistoryCreateArgs = { + /** + * Select specific fields to fetch from the OilPriceHistory + */ + select?: Prisma.OilPriceHistorySelect | null + /** + * Omit specific fields from the OilPriceHistory + */ + omit?: Prisma.OilPriceHistoryOmit | null + /** + * The data needed to create a OilPriceHistory. + */ + data: Prisma.XOR +} + +/** + * OilPriceHistory createMany + */ +export type OilPriceHistoryCreateManyArgs = { + /** + * The data used to create many OilPriceHistories. + */ + data: Prisma.OilPriceHistoryCreateManyInput | Prisma.OilPriceHistoryCreateManyInput[] + skipDuplicates?: boolean +} + +/** + * OilPriceHistory update + */ +export type OilPriceHistoryUpdateArgs = { + /** + * Select specific fields to fetch from the OilPriceHistory + */ + select?: Prisma.OilPriceHistorySelect | null + /** + * Omit specific fields from the OilPriceHistory + */ + omit?: Prisma.OilPriceHistoryOmit | null + /** + * The data needed to update a OilPriceHistory. + */ + data: Prisma.XOR + /** + * Choose, which OilPriceHistory to update. + */ + where: Prisma.OilPriceHistoryWhereUniqueInput +} + +/** + * OilPriceHistory updateMany + */ +export type OilPriceHistoryUpdateManyArgs = { + /** + * The data used to update OilPriceHistories. + */ + data: Prisma.XOR + /** + * Filter which OilPriceHistories to update + */ + where?: Prisma.OilPriceHistoryWhereInput + /** + * Limit how many OilPriceHistories to update. + */ + limit?: number +} + +/** + * OilPriceHistory upsert + */ +export type OilPriceHistoryUpsertArgs = { + /** + * Select specific fields to fetch from the OilPriceHistory + */ + select?: Prisma.OilPriceHistorySelect | null + /** + * Omit specific fields from the OilPriceHistory + */ + omit?: Prisma.OilPriceHistoryOmit | null + /** + * The filter to search for the OilPriceHistory to update in case it exists. + */ + where: Prisma.OilPriceHistoryWhereUniqueInput + /** + * In case the OilPriceHistory found by the `where` argument doesn't exist, create a new OilPriceHistory with this data. + */ + create: Prisma.XOR + /** + * In case the OilPriceHistory was found with the provided `where` argument, update it with this data. + */ + update: Prisma.XOR +} + +/** + * OilPriceHistory delete + */ +export type OilPriceHistoryDeleteArgs = { + /** + * Select specific fields to fetch from the OilPriceHistory + */ + select?: Prisma.OilPriceHistorySelect | null + /** + * Omit specific fields from the OilPriceHistory + */ + omit?: Prisma.OilPriceHistoryOmit | null + /** + * Filter which OilPriceHistory to delete. + */ + where: Prisma.OilPriceHistoryWhereUniqueInput +} + +/** + * OilPriceHistory deleteMany + */ +export type OilPriceHistoryDeleteManyArgs = { + /** + * Filter which OilPriceHistories to delete + */ + where?: Prisma.OilPriceHistoryWhereInput + /** + * Limit how many OilPriceHistories to delete. + */ + limit?: number +} + +/** + * OilPriceHistory without action + */ +export type OilPriceHistoryDefaultArgs = { + /** + * Select specific fields to fetch from the OilPriceHistory + */ + select?: Prisma.OilPriceHistorySelect | null + /** + * Omit specific fields from the OilPriceHistory + */ + omit?: Prisma.OilPriceHistoryOmit | null +} diff --git a/prisma/migrations/20260807104432_add_oil_price_history/migration.sql b/prisma/migrations/20260807104432_add_oil_price_history/migration.sql new file mode 100644 index 0000000..f2377cf --- /dev/null +++ b/prisma/migrations/20260807104432_add_oil_price_history/migration.sql @@ -0,0 +1,17 @@ +-- 浙江省油价历史表 +-- - date: 调价日次日 (即数据实际抓取日, 便于按时间排序) +-- - province + fuel: 浙江 / 92/95/0 +-- - unique (date, province, fuel): 防 cron 重复入库 +-- - DOUBLE 容纳 999.999 元/升 +CREATE TABLE OilPriceHistory ( + id INT NOT NULL AUTO_INCREMENT, + date DATETIME(3) NOT NULL, + province VARCHAR(191) NOT NULL, + fuel VARCHAR(8) NOT NULL, + price DOUBLE NOT NULL, + source VARCHAR(191) NOT NULL DEFAULT 'apizero', + createdAt DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), + PRIMARY KEY (id), + UNIQUE INDEX OilPriceHistory_date_province_fuel_key(date, province, fuel), + INDEX OilPriceHistory_province_fuel_date_idx(province, fuel, date) +) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 2500fa1..9834d92 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -181,3 +181,22 @@ model ScraperCache { } + + +// 浙江省油价历史 (apizero price 接口每日抓取) +// 每天 04:00 cron 触发: 检查 schedule 里待定且 <= 昨天的调价日, 抓 price?province=浙江 存本表 +// unique (date, province, fuel) 防重复 +model OilPriceHistory { + id Int @id @default(autoincrement()) + date DateTime // 调价日次日 (即数据实际抓取日) + province String // '浙江' + fuel String // '92' | '95' | '0' + price Float // 油价 (元/升, 4 位小数足够) + source String @default("apizero") + createdAt DateTime @default(now()) + + @@unique([date, province, fuel]) + @@index([province, fuel, date]) +} + + diff --git a/scripts/import-oil-history.mjs b/scripts/import-oil-history.mjs new file mode 100644 index 0000000..ae71225 --- /dev/null +++ b/scripts/import-oil-history.mjs @@ -0,0 +1,119 @@ +#!/usr/bin/env node +// 一次性导入浙江省油价历史 (2025-2026) +// 来源: 手工整理 (省发改委公告 / 潮新闻 / 钱江晚报 / 杭州日报 / 杭州网 等) +// 用法: node --experimental-strip-types --no-warnings scripts/import-oil-history.mjs [--dry] + +import path from 'node:path' +import { fileURLToPath, pathToFileURL } from 'node:url' +import 'dotenv/config' + +const __filename = fileURLToPath(import.meta.url) +const __dirname = path.dirname(__filename) +const ROOT = path.resolve(__dirname, '..') + +// 接入 prisma (用 file:// URL 避免 Windows 绝对路径 import 报错) +const adapterMod = await import('@prisma/adapter-mariadb') +const clientPath = pathToFileURL(path.join(ROOT, 'generated/prisma/client.ts')).href +const { PrismaClient } = await import(clientPath) + +const adapter = new adapterMod.PrismaMariaDb((() => { + const u = new URL(process.env.DATABASE_URL) + return { + host: u.hostname, + port: Number(u.port) || 3306, + user: decodeURIComponent(u.username), + password: decodeURIComponent(u.password), + database: u.pathname.replace(/^\//, ''), + } +})()) +const prisma = new PrismaClient({ adapter }) + +// 数据: [调价日, 92, 95, 0, source] +const RAW = [ + ['2026-07-31', 7.94, 8.44, 7.62, 'manual'], + ['2026-07-17', 7.39, 7.86, 7.06, 'manual'], + ['2026-06-18', 7.91, 8.41, 7.59, 'manual'], + ['2026-06-04', 8.32, 8.85, 8.02, 'manual'], + ['2026-05-21', 8.74, 9.30, 8.45, 'manual'], + ['2026-02-03', 6.91, 7.35, 6.56, 'manual'], + ['2025-12-22', 6.68, 7.11, 6.32, 'manual'], + ['2025-12-08', 6.82, 7.25, 6.46, 'manual'], + ['2025-11-24', 6.86, null, null, 'manual'], + ['2025-11-10', 6.92, 7.36, 6.57, 'manual'], + ['2025-10-13', 7.03, 7.48, 6.68, 'manual'], + ['2025-06-17', 7.15, 7.60, 6.81, 'manual'], + ['2025-06-03', 6.94, 7.38, 6.59, 'manual'], +] + +const PROVINCE = '浙江' +const FUEL_COLS = [ + { fuel: '92', idx: 1 }, + { fuel: '95', idx: 2 }, + { fuel: '0', idx: 3 }, +] + +const DRY = process.argv.includes('--dry') + +async function main() { + console.log('=== 浙江省油价历史导入 ===') + console.log('dry run:', DRY) + console.log('') + + let inserted = 0 + let updated = 0 + let skipped = 0 + + for (const row of RAW) { + const dateStr = row[0] + const source = row[4] + for (const { fuel, idx } of FUEL_COLS) { + const price = row[idx] + if (price == null || Number.isNaN(price)) { + console.log('[SKIP] ' + dateStr + ' ' + fuel + ': 价格为空') + skipped++ + continue + } + const date = new Date(dateStr + 'T00:00:00') + if (DRY) { + console.log('[DRY] ' + dateStr + ' ' + fuel + ' = ' + price + ' (source=' + source + ')') + inserted++ + continue + } + try { + await prisma.oilPriceHistory.create({ + data: { date, province: PROVINCE, fuel, price, source }, + }) + console.log('[OK] ' + dateStr + ' ' + fuel + ' = ' + price) + inserted++ + } catch (e) { + if (e?.code === 'P2002') { + try { + await prisma.oilPriceHistory.update({ + where: { date_province_fuel: { date, province: PROVINCE, fuel } }, + data: { price, source }, + }) + console.log('[UPD] ' + dateStr + ' ' + fuel + ' = ' + price) + updated++ + } catch (e2) { + console.log('[ERR] ' + dateStr + ' ' + fuel + ': ' + e2.message) + } + } else { + console.log('[ERR] ' + dateStr + ' ' + fuel + ': ' + e.message) + } + } + } + } + + console.log('') + console.log('=== 汇总 ===') + console.log('插入: ' + inserted) + console.log('更新: ' + updated) + console.log('跳过: ' + skipped) + + await prisma.$disconnect() +} + +main().catch((e) => { + console.error(e) + process.exit(1) +}) diff --git a/server/apizero/cache.js b/server/apizero/cache.js new file mode 100644 index 0000000..1f907b1 --- /dev/null +++ b/server/apizero/cache.js @@ -0,0 +1,46 @@ +// apizero 接口的文件缓存 +// - 按 key 存 JSON 到磁盘: /.json +// - 存在性检查: 文件在即视为有效 (用户要求: "同一个年份只要存在就不再调用接口") +// - 不做 TTL: 用户没要求, 也避免误命中过期数据 +// +// 环境变量: +// APIZERO_CACHE_DIR 缓存目录 (默认 /cache/apizero) +// +// 未来若要加 TTL / DB 后端, 替换本文件即可, 上层调用方不变. +import fs from 'node:fs' +import path from 'node:path' + +function dir() { + return process.env.APIZERO_CACHE_DIR + ? path.resolve(process.env.APIZERO_CACHE_DIR) + : path.resolve(process.cwd(), 'cache', 'apizero') +} + +// 读缓存, 不存在返回 null +export function read(key) { + const p = path.join(dir(), key + '.json') + if (!fs.existsSync(p)) return null + try { + const raw = fs.readFileSync(p, 'utf8') + return JSON.parse(raw) + } catch (e) { + console.warn(`[apizero-cache] 读 ${key} 失败, 忽略:`, e.message) + return null + } +} + +// 写缓存 (原子: 先写 .tmp 再 rename) +export function write(key, data) { + const d = dir() + fs.mkdirSync(d, { recursive: true }) + const final = path.join(d, key + '.json') + const tmp = final + '.tmp.' + process.pid + fs.writeFileSync(tmp, JSON.stringify(data), 'utf8') + fs.renameSync(tmp, final) + return final +} + +// 存在性检查 +export function has(key) { + return fs.existsSync(path.join(dir(), key + '.json')) +} diff --git a/server/apizero/client.js b/server/apizero/client.js new file mode 100644 index 0000000..9dfd1aa --- /dev/null +++ b/server/apizero/client.js @@ -0,0 +1,77 @@ +// apizero (https://apizero.cn) 通用 HTTP 客户端 +// - 统一从 env APIZERO_KEY 读取 API key (test key 也能用) +// - 统一 QPS 节流 (apizero 限制 3 req/s) +// - 统一错误格式: 抛出 ApizeroError(code, message, httpStatus) +// - 所有 apizero 接口都进这一层, 后续新增模块复用 +// +// 依赖: 原生 fetch (Node 18+) + +// 简易令牌桶, 限速 3 req/s +let lastCallAt = 0 +const MIN_INTERVAL_MS = 1000 / 3 // ~333ms + +async function throttle() { + const now = Date.now() + const wait = lastCallAt + MIN_INTERVAL_MS - now + if (wait > 0) await new Promise((r) => setTimeout(r, wait)) + lastCallAt = Date.now() +} + +// apizero 标准错误 +export class ApizeroError extends Error { + constructor(code, message, httpStatus) { + super(message || `apizero error code=${code}`) + this.name = 'ApizeroError' + this.code = code + this.httpStatus = httpStatus + } +} + +const BASE_URL = 'https://v1.apizero.cn/api' + +// 读 key: 优先 env APIZERO_KEY, 否则用空 (匿名调用, 配额更小) +function getKey() { + return process.env.APIZERO_KEY || '' +} + +// 通用 GET 入口 +// - endpoint: 'oil-price-forecast' (不带 /api 前缀) +// - params: 普通对象 +// 返回: apizero 的 data 字段 (已解一层) +export async function get(endpoint, params = {}) { + await throttle() + + const qs = new URLSearchParams() + for (const [k, v] of Object.entries(params)) { + if (v !== undefined && v !== null && v !== '') qs.set(k, String(v)) + } + const key = getKey() + if (key) qs.set('key', key) + + const url = `${BASE_URL}/${endpoint}?${qs.toString()}` + let res + try { + res = await fetch(url, { method: 'GET', headers: { 'Accept': 'application/json' } }) + } catch (e) { + throw new ApizeroError('NETWORK', `apizero 网络错误: ${e.message}`, 0) + } + + // HTTP 层错误 + if (!res.ok) { + let body = '' + try { body = await res.text() } catch { /* ignore */ } + throw new ApizeroError('HTTP', `apizero HTTP ${res.status}: ${body.substring(0, 200)}`, res.status) + } + + // 解析 body + let json + try { json = await res.json() } + catch (e) { throw new ApizeroError('PARSE', 'apizero 响应非 JSON: ' + e.message, res.status) } + + // apizero 业务层错误: code !== 0 + if (json && typeof json.code === 'number' && json.code !== 0) { + throw new ApizeroError(json.code, json.msg || 'apizero 业务错误', res.status) + } + + return json && json.data !== undefined ? json.data : json +} diff --git a/server/apizero/index.js b/server/apizero/index.js new file mode 100644 index 0000000..95cbd21 --- /dev/null +++ b/server/apizero/index.js @@ -0,0 +1,6 @@ +// apizero 模块统一出口 +// 后续新增 apizero 接口就在这里再 export 一行 +export * as oil from './oil-price-forecast.js' +export * as history from './oil-history.js' +export { ApizeroError } from './client.js' + diff --git a/server/apizero/oil-history.js b/server/apizero/oil-history.js new file mode 100644 index 0000000..3d4b419 --- /dev/null +++ b/server/apizero/oil-history.js @@ -0,0 +1,87 @@ +// 浙江省油价历史: 走 Prisma 落库 + apizero price 接口写入 +// 设计: +// - 每天 04:00 cron 检查 schedule, 待定且 <= 昨天的调价日 -> 抓 price?province=浙江 存本表 +// - unique (date, province, fuel) 防重复 +// - 查询 API: 取某省某油品最近 N 天 (默认 180) +import { prisma } from '../db.js' +import * as client from './client.js' + +const PROVINCE = '浙江' +// 油品 -> apizero prices 对象里的 key (price action 返回 "92号汽油" 这种带后缀的 key) +const FUEL_KEYS = { + '92': '92号汽油', + '95': '95号汽油', + '0': '0号柴油', +} + +// 解析 apizero price action 返回的 prices (中文 key) -> 标准 fuel code +function parsePrice(data) { + if (!data || !data.prices) throw new Error('apizero 响应无 prices 字段') + const out = {} + for (const [fuel, label] of Object.entries(FUEL_KEYS)) { + const raw = data.prices[label] + if (typeof raw === 'string') { + // "7.64 元/升" -> 7.64 + const m = raw.match(/^([\d.]+)/) + if (m) out[fuel] = parseFloat(m[1]) + } else if (typeof raw === 'number') { + out[fuel] = raw + } + } + return out +} + +// 抓一次浙江当前价并入库 (date = 今日) +// 返回 { inserted, skipped } (按 unique 约束: 已存在则 skip) +export async function fetchAndStore() { + const data = await client.get('oil-price-forecast', { action: 'price', province: PROVINCE }) + const prices = parsePrice(data) + if (Object.keys(prices).length === 0) { + throw new Error('apizero 返回价格为空') + } + const date = new Date() + // 抹掉时分秒, 便于按天比较 + date.setHours(0, 0, 0, 0) + + let inserted = 0 + let skipped = 0 + for (const [fuel, price] of Object.entries(prices)) { + try { + await prisma.oilPriceHistory.create({ + data: { date, province: PROVINCE, fuel, price, source: 'apizero' }, + }) + inserted++ + } catch (e) { + // P2002: unique 冲突 -> 跳过 + if (e?.code === 'P2002') skipped++ + else throw e + } + } + return { inserted, skipped, date: date.toISOString().slice(0, 10) } +} + +// 查询某省某油品最近 N 天 +// province 必填, 默认 浙江 +// fuel 可选, 留空返回 4 个油品 +// days 默认 180 +export async function query({ province = PROVINCE, fuel, days = 180 }) { + const since = new Date() + since.setDate(since.getDate() - days) + since.setHours(0, 0, 0, 0) + + const where = { province, date: { gte: since } } + if (fuel) where.fuel = fuel + + const rows = await prisma.oilPriceHistory.findMany({ + where, + orderBy: [{ date: 'asc' }], + }) + + // 整形: Decimal -> number + return rows.map((r) => ({ + date: r.date.toISOString().slice(0, 10), + province: r.province, + fuel: r.fuel, + price: Number(r.price), + })) +} diff --git a/server/apizero/oil-price-forecast.js b/server/apizero/oil-price-forecast.js new file mode 100644 index 0000000..2f2ae3c --- /dev/null +++ b/server/apizero/oil-price-forecast.js @@ -0,0 +1,41 @@ +// apizero: 今日油价 (oil-price-forecast) +// 4 个 action: +// forecast - 油价 + 国际原油 + 下次调价预测 (每次都查实时, 不缓存) +// price - 单省油价 +// price-all - 32 省全部油价 +// schedule - 某年调价日历 (按 year 缓存到文件, 同年份不重复调) +// +// 文档: https://apizero.cn/aidocs/oil-price-forecast/raw.md +import * as client from './client.js' +import * as cache from './cache.js' + +// 调价日历: 按年份缓存, 文件存在即视为有效, 不重复调用 +// cache key 形如 "oil-schedule-2026" +export async function getSchedule(year) { + const y = Number(year) + if (!Number.isInteger(y) || y < 2025 || y > 2026) { + throw new client.ApizeroError(4000, `year 不在 2025-2026 范围: ${year}`, 400) + } + const cacheKey = `oil-schedule-${y}` + const hit = cache.read(cacheKey) + if (hit) return { ...hit, _cached: true } + const data = await client.get('oil-price-forecast', { action: 'schedule', year: y }) + cache.write(cacheKey, data) + return { ...data, _cached: false } +} + +// 实时: 国际原油 + 下次调价预测 +export async function getForecast() { + return client.get('oil-price-forecast', { action: 'forecast' }) +} + +// 单省油价 +export async function getPrice(province) { + if (!province) throw new client.ApizeroError(4000, 'province 必填', 400) + return client.get('oil-price-forecast', { action: 'price', province }) +} + +// 32 省全部油价 +export async function getPriceAll() { + return client.get('oil-price-forecast', { action: 'price-all' }) +} diff --git a/server/cron.js b/server/cron.js index 5614e8c..666808d 100644 --- a/server/cron.js +++ b/server/cron.js @@ -3,6 +3,7 @@ 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' +import { ApizeroError, oil, history } from './apizero/index.js' function parseUrl(url) { const u = new URL(url) @@ -33,4 +34,43 @@ function scheduleNews() { console.log('[cron] 已注册: 每天 03:00 拉取新闻 + 跨源报警检测') } +// 每天凌晨 4:00 抓浙江油价历史 +// 逻辑: 拉今年 schedule, 检查待定且 <= 昨天的调价日, 命中就抓 price?province=浙江 存库 +// - 0 命中: 不调 apizero (省配额) +// - >0 命中: 调一次, 4 个油品批量入库 (unique 兜底去重) +function scheduleOilHistory() { + cron.schedule('0 4 * * *', async () => { + console.log('[cron] 4:00 油价历史触发') + try { + const year = new Date().getFullYear() + const sched = await oil.getSchedule(year) + const list = sched.schedule || [] + // 待定 且 日期 <= 昨天 + const today = new Date() + today.setHours(0, 0, 0, 0) + const yesterdayMs = today.getTime() - 86400000 + const pendingPast = list.filter((it) => { + if (it.status !== '待定') return false + const t = new Date(it.date + 'T00:00:00').getTime() + return Number.isFinite(t) && t <= yesterdayMs + }) + console.log('[cron] 待定且已过的调价日: ' + pendingPast.length + ' 个') + if (pendingPast.length === 0) { + console.log('[cron] 油价历史: 0 命中, 跳过 apizero 调用') + return + } + const r = await history.fetchAndStore() + console.log('[cron] 油价历史入库: 新增 ' + r.inserted + ' / 跳过 ' + r.skipped + ' (date=' + r.date + ')') + } catch (e) { + if (e instanceof ApizeroError) { + console.error('[cron] 油价历史 apizero 错误: code=' + e.code + ' msg=' + e.message) + } else { + console.error('[cron] 油价历史任务失败:', e.message) + } + } + }) + console.log('[cron] 已注册: 每天 04:00 浙江油价历史抓取') +} + scheduleNews() +scheduleOilHistory() diff --git a/server/index.js b/server/index.js index ad2464a..d2812ca 100644 --- a/server/index.js +++ b/server/index.js @@ -9,6 +9,7 @@ import newsRouter from './routes/news.js' import alertsRouter from './routes/alerts.js' import articlesRouter from './routes/articles.js' import otaRouter from './routes/ota.js' +import apizeroRouter from './routes/apizero.js' import monitorsRouter from './routes/monitors.js' const PORT = Number(process.env.PORT) || 3001 @@ -29,6 +30,7 @@ app.use('/api', newsRouter) app.use('/api', alertsRouter) app.use('/api', articlesRouter) app.use('/api', otaRouter) +app.use('/api', apizeroRouter) app.use('/api', monitorsRouter) // 静态资源 (Vite build 产物) @@ -56,3 +58,4 @@ 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/apizero.js b/server/routes/apizero.js new file mode 100644 index 0000000..81371ad --- /dev/null +++ b/server/routes/apizero.js @@ -0,0 +1,63 @@ +// apizero 代理路由 (前端不直接调 apizero, 一律走后端, key 不外泄) +// +// GET /api/apizero/oil/forecast - 油价 + 预测 (实时) +// GET /api/apizero/oil/price-all - 32 省油价 +// GET /api/apizero/oil/price?province= - 单省油价 +// GET /api/apizero/oil/schedule?year= - 某年调价日历 (按年缓存) +// +// 错误: apizero 错误统一包成 502 (上游错误) 或 400 (参数错误) +import { Router } from 'express' +import { authRequired } from '../middleware.js' +import { ApizeroError, oil, history } from '../apizero/index.js' + +const router = Router() +router.use(authRequired) + +function handleApizeroError(e, res, next) { + if (e instanceof ApizeroError) { + // 参数错 -> 400, 上游错 -> 502, QPS 限流 / 额度用完 -> 503 + if (e.httpStatus === 400) return res.status(400).json({ error: e.message, apizero_code: e.code }) + if (e.code === 4029 || e.code === 4030) return res.status(503).json({ error: e.message, apizero_code: e.code }) + return res.status(502).json({ error: e.message, apizero_code: e.code }) + } + next(e) +} + +// 实时: 油价 + 国际原油 + 下次调价预测 +router.get('/apizero/oil/forecast', async (req, res, next) => { + try { res.json(await oil.getForecast()) } + catch (e) { handleApizeroError(e, res, next) } +}) + +// 32 省油价 +router.get('/apizero/oil/price-all', async (req, res, next) => { + try { res.json(await oil.getPriceAll()) } + catch (e) { handleApizeroError(e, res, next) } +}) + +// 单省油价 +router.get('/apizero/oil/price', async (req, res, next) => { + try { res.json(await oil.getPrice(req.query.province)) } + catch (e) { handleApizeroError(e, res, next) } +}) + +// 调价日历 (按年缓存) +router.get('/apizero/oil/schedule', async (req, res, next) => { + try { res.json(await oil.getSchedule(req.query.year)) } + catch (e) { handleApizeroError(e, res, next) } +}) + +export default router + +// 浙江省油价历史 (DB) +// GET /api/apizero/oil/history?fuel=92&days=180 +// - fuel: 92 / 95 / 0 (留空 = 3 个油品都返回) +// - days: 默认 180 (半年) +router.get('/apizero/oil/history', async (req, res, next) => { + try { + const fuel = req.query.fuel ? String(req.query.fuel) : undefined + const days = Math.max(1, Math.min(Number(req.query.days) || 180, 730)) + const items = await history.query({ fuel, days }) + res.json({ items, fuel: fuel || 'all', days }) + } catch (e) { next(e) } +}) diff --git a/src/api/oil.js b/src/api/oil.js new file mode 100644 index 0000000..913a375 --- /dev/null +++ b/src/api/oil.js @@ -0,0 +1,32 @@ +// 前端油价 API: 一律走后端 /api/apizero/oil/*, 不直接调 apizero (key 不外泄) +import { api, getApiBase } from './client.js' + +// 实时: 油价 + 国际原油 + 下次调价预测 +export async function getOilForecast() { + return api('/apizero/oil/forecast') +} + +// 32 省油价 (可暂未在 UI 用, 留作 API 暴露) +export async function getOilPriceAll() { + return api('/apizero/oil/price-all') +} + +// 单省油价 +export async function getOilPrice(province) { + return api('/apizero/oil/price?province=' + encodeURIComponent(province)) +} + +// 某年调价日历 (后端按年缓存, 同年份不会重复调 apizero) +export async function getOilSchedule(year) { + return api('/apizero/oil/schedule?year=' + encodeURIComponent(year)) +} + +// 浙江省油价历史 (走 DB, 由 cron 每天 04:00 抓取并落库) +// fuel: '92' | '95' | '0' | undefined (留空 = 3 个油品) +// days: 默认 180 (半年) +export async function getOilHistory({ fuel, days = 180 } = {}) { + const qs = new URLSearchParams() + if (fuel) qs.set('fuel', fuel) + qs.set('days', String(days)) + return api('/apizero/oil/history?' + qs.toString()) +} diff --git a/src/pages/MacroPage.jsx b/src/pages/MacroPage.jsx index 23e327a..de329b6 100644 --- a/src/pages/MacroPage.jsx +++ b/src/pages/MacroPage.jsx @@ -5,23 +5,29 @@ import DataView from './macro/DataView.jsx' import StrategyView from './macro/StrategyView.jsx' import ArticlesView from './macro/ArticlesView.jsx' import ArticleDetail from './macro/ArticleDetail.jsx' +import OilPage from './macro/OilPage.jsx' -// 宏观: 顶栏 3 tab (经济文章 / 经济数据 / 策略研究), 默认 经济数据 -// /macro → 重定向到 /macro/data -// /macro/data → 经济数据 (默认) -// /macro/strategy→ 策略研究 -// /macro/articles→ 经济文章 +// 宏观: 顶栏 4 tab (油价 / 经济数据 / 策略研究 / 经济文章), 默认 油价 +// /macro → 显示 oil tab (本组件 activeFromPath 决定) +// /macro/oil → 油价 (新增) +// /macro/data → 经济数据 +// /macro/strategy → 策略研究 +// /macro/articles → 经济文章 // /macro/articles/:slug → 文章详情 const TABS = [ + { key: 'oil', label: '油价', path: '/macro/oil' }, { key: 'data', label: '经济数据', path: '/macro/data' }, { key: 'strategy', label: '策略研究', path: '/macro/strategy' }, { key: 'articles', label: '经济文章', path: '/macro/articles' }, ] function activeFromPath(pathname) { + if (pathname.startsWith('/macro/oil')) return 'oil' if (pathname.startsWith('/macro/articles')) return 'articles' if (pathname.startsWith('/macro/strategy')) return 'strategy' - return 'data' + if (pathname.startsWith('/macro/data')) return 'data' + // 父路由 /macro 或 / 走 Tab 列表第一个 (油价) + return 'oil' } export default function MacroPage() { @@ -33,6 +39,7 @@ export default function MacroPage() { key: t.key, label: t.label, render: () => { + if (t.key === 'oil') return if (t.key === 'data') return if (t.key === 'strategy') return if (t.key === 'articles') return @@ -46,7 +53,6 @@ export default function MacroPage() { } // 详情页 /macro/articles/:slug 和 /macro/data/:name 单独走 React Router 渲染, 不参与滑屏 - // 这样浏览器/手机物理返回键也能正常回到列表 if (location.pathname.match(/^\/macro\/(articles|data|strategy)\/[^/]+$/)) { return ( @@ -62,4 +68,4 @@ export default function MacroPage() { ) -} \ No newline at end of file +} diff --git a/src/pages/macro/OilPage.jsx b/src/pages/macro/OilPage.jsx new file mode 100644 index 0000000..41a3813 --- /dev/null +++ b/src/pages/macro/OilPage.jsx @@ -0,0 +1,250 @@ +import { useEffect, useMemo, useState } from 'react' +import { Card, DotLoading, Empty, ErrorBlock } from 'antd-mobile' +import { + CartesianGrid, + Legend, + Line, + LineChart, + ResponsiveContainer, + Tooltip, + XAxis, + YAxis, +} from 'recharts' +import { getOilForecast, getOilHistory, getOilSchedule } from '../../api/oil.js' + +// 油价页 (新): +// - 上: 下次调价预测 (无 WTI / 无柱状图) +// - 中: 浙江省最近半年价格走势 (3 油品折线, 一张图) +// - 下: 调价日历 (按年切换) +// 数据源: +// - 预测/日历: apizero 实时 (后端代理) +// - 走势: DB oil_price_history 表 (cron 每天 04:00 抓浙江 3 油品入库) + +const FUEL_LABELS = { + '92': '92# 汽油', + '95': '95# 汽油', + '0': '0# 柴油', +} +// 3 油品各自配色 (与原柱状图色调保持一致) +const FUEL_COLORS = { + '92': '#1677ff', + '95': '#52c41a', + '0': '#888', +} + +function n(v, d = 2) { return Number.isFinite(Number(v)) ? Number(v).toFixed(d) : '-' } + +// 调价预测 (保留, 但不显示 WTI / 布伦特) +function ForecastPanel() { + const [forecast, setForecast] = useState(null) + const [loading, setLoading] = useState(true) + const [err, setErr] = useState('') + + useEffect(() => { + let cancelled = false + setLoading(true) + setErr('') + getOilForecast() + .then((d) => { if (!cancelled) setForecast(d) }) + .catch((e) => !cancelled && setErr(e.message || '加载失败')) + .finally(() => !cancelled && setLoading(false)) + return () => { cancelled = true } + }, []) + + if (loading) return
加载中...
+ if (err) return + + const p = forecast?.prediction + return ( + +
下次调价预测
+
+
+ 调价日 + {forecast?.next_adjust_date || '-'} + 剩 {forecast?.days_remaining ?? '-'} 天 +
+
+ 方向 + + {p?.direction_emoji || ''} {p?.direction || '-'} + + 置信度 {p?.confidence || '-'} +
+
+ 预计幅度 + + {p?.estimated_change_per_ton != null + ? `${p.estimated_change_per_ton > 0 ? '+' : ''}${p.estimated_change_per_ton} 元/吨` + : '-'} + {p?.estimated_change_per_liter != null && ( + ({p.estimated_change_per_liter > 0 ? '+' : ''}{p.estimated_change_per_liter} 元/升) + )} + +
+ {p?.analysis && ( +
{p.analysis}
+ )} +
+
+ ) +} + +// 浙江省最近半年价格走势 +function HistoryPanel() { + const [data, setData] = useState([]) + const [loading, setLoading] = useState(true) + const [err, setErr] = useState('') + + useEffect(() => { + let cancelled = false + setLoading(true) + setErr('') + getOilHistory({ days: 180 }) + .then((d) => { if (!cancelled) setData(d.items || []) }) + .catch((e) => !cancelled && setErr(e.message || '加载失败')) + .finally(() => !cancelled && setLoading(false)) + return () => { cancelled = true } + }, []) + + // 整形: rows = [{date, fuel, price}] -> 3 油品并排 + // pivot: [{date, 92, 95, 0}] + const chartData = useMemo(() => { + const m = new Map() + for (const r of data) { + if (!m.has(r.date)) m.set(r.date, { date: r.date }) + m.get(r.date)[r.fuel] = r.price + } + return Array.from(m.values()).sort((a, b) => a.date.localeCompare(b.date)) + }, [data]) + + // 3 油品都有数据? + const hasData = chartData.length > 0 + + return ( + +
浙江省最近半年价格走势
+ {loading &&
加载中...
} + {err && } + {!loading && !err && !hasData && ( + + )} + {!loading && !err && hasData && ( + <> +
+ + + + + + `${Number(v).toFixed(3)} 元/升`} /> + + {Object.keys(FUEL_LABELS).map((k) => ( + + ))} + + +
+
共 {chartData.length} 个数据点 (调价次日入库)
+ + )} +
+ ) +} + +// 调价日历 (不变) +function SchedulePanel() { + const [year, setYear] = useState(new Date().getFullYear()) + const [data, setData] = useState(null) + const [loading, setLoading] = useState(true) + const [err, setErr] = useState('') + + useEffect(() => { + let cancelled = false + setLoading(true) + setErr('') + getOilSchedule(year) + .then((d) => { if (!cancelled) setData(d) }) + .catch((e) => !cancelled && setErr(e.message || '加载失败')) + .finally(() => !cancelled && setLoading(false)) + return () => { cancelled = true } + }, [year]) + + const byMonth = useMemo(() => { + const m = {} + if (!data?.schedule) return m + for (const it of data.schedule) { + const mm = it.date.slice(0, 7) + if (!m[mm]) m[mm] = [] + m[mm].push(it) + } + return m + }, [data]) + + return ( + +
+
调价日历
+
+ {[2025, 2026].map((y) => ( + + ))} +
+
+ {data?._cached &&
本次来自本地缓存, 不消耗 apizero 配额
} + {loading &&
加载中...
} + {err && } + {!loading && !err && data && ( + <> +
+ {data.year} 年共 {data.total_adjustments} 个调价窗口 + {data.next_adjust_date && ( + 下一个: {data.next_adjust_date} (剩 {data.days_remaining} 天) + )} +
+
+ {Object.keys(byMonth).sort().map((m) => ( +
+
{m}
+
+ {byMonth[m].map((it) => ( +
+
{it.date.slice(8)}
+
{it.status}
+
+ ))} +
+
+ ))} +
+ + )} +
+ ) +} + +// 油价页入口: 预测 + 走势 + 日历 +export default function OilPage() { + return ( +
+ + + +
+ ) +} diff --git a/src/styles/globals.css b/src/styles/globals.css index 4b5dd65..379a93a 100644 --- a/src/styles/globals.css +++ b/src/styles/globals.css @@ -294,3 +294,168 @@ input, textarea, select { font: inherit; } font-size: 12px; word-break: break-word; } + + +/* ================== 油价页 (Macro/Oil) ================== */ +.oil-page { + padding: 0 0 16px; + display: flex; + flex-direction: column; + gap: 12px; +} +.oil-card { + margin: 0 12px; + border-radius: 10px; +} +.oil-card .adm-card-body { + padding: 12px; +} +.oil-card-title { + font-size: 15px; + font-weight: 600; + color: var(--color-text); + margin-bottom: 8px; +} +.oil-card-title-row { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 8px; +} +.oil-card-title-row .oil-card-title { margin-bottom: 0; } +.oil-fuel-picker { + font-size: 13px; + color: var(--color-primary); + text-decoration: none; +} +.oil-crude { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 8px; + margin-bottom: 8px; +} +.oil-crude-item { + background: #f7f8fa; + border-radius: 8px; + padding: 10px; + text-align: center; +} +.oil-crude-label { font-size: 12px; color: var(--color-muted); } +.oil-crude-value { + font-size: 22px; + font-weight: 700; + font-variant-numeric: tabular-nums; + margin: 2px 0; +} +.oil-crude-value.up { color: #ff3141; } +.oil-crude-value.down { color: #00b578; } +.oil-crude-unit { font-size: 12px; font-weight: 400; color: var(--color-muted); margin-left: 2px; } +.oil-crude-change { font-size: 12px; font-variant-numeric: tabular-nums; } +.oil-crude-change.up { color: #ff3141; } +.oil-crude-change.down { color: #00b578; } + +.oil-prediction { + border-top: 1px solid var(--color-border); + padding-top: 8px; +} +.oil-pred-row { + display: flex; + align-items: center; + gap: 8px; + padding: 4px 0; + font-size: 13px; +} +.oil-pred-label { color: var(--color-muted); min-width: 76px; } +.oil-pred-value { color: var(--color-text); flex: 1; font-weight: 600; } +.oil-pred-sub { color: var(--color-muted); font-weight: 400; } +.oil-pred-tag { + font-size: 11px; + background: #f0f5ff; + color: var(--color-primary); + padding: 2px 6px; + border-radius: 4px; +} +.oil-pred-direction { + font-weight: 600; + font-size: 14px; +} +.oil-pred-direction.上涨 { color: #ff3141; } +.oil-pred-direction.下跌 { color: #00b578; } +.oil-pred-direction.搁浅 { color: #888; } +.oil-pred-analysis { + margin-top: 6px; + font-size: 12px; + color: var(--color-muted); + line-height: 1.55; + background: #f7f8fa; + padding: 8px 10px; + border-radius: 6px; +} + +.oil-chart { margin: 0 -4px; } +.oil-chart-tip { + font-size: 11px; + color: var(--color-muted); + text-align: center; + margin-top: 4px; +} + +.oil-year-tabs { display: flex; gap: 4px; } +.oil-year-tab { + border: 1px solid var(--color-border); + background: #fff; + color: var(--color-text); + padding: 4px 10px; + border-radius: 14px; + font-size: 12px; + cursor: pointer; +} +.oil-year-tab.active { + background: var(--color-primary); + color: #fff; + border-color: var(--color-primary); +} +.oil-cache-hint { + font-size: 11px; + color: #00b578; + background: #e6f7ee; + padding: 4px 8px; + border-radius: 4px; + margin-bottom: 8px; +} +.oil-schedule-meta { + font-size: 13px; + color: var(--color-muted); + margin-bottom: 10px; + display: flex; + align-items: center; + gap: 8px; + flex-wrap: wrap; +} +.oil-schedule-list { display: flex; flex-direction: column; gap: 10px; } +.oil-month-label { + font-size: 12px; + font-weight: 600; + color: var(--color-text); + margin-bottom: 4px; +} +.oil-month-items { + display: grid; + grid-template-columns: repeat(5, 1fr); + gap: 6px; +} +.oil-day { + border-radius: 6px; + padding: 6px 4px; + text-align: center; + font-size: 11px; + font-variant-numeric: tabular-nums; +} +.oil-day-date { font-weight: 600; font-size: 13px; } +.oil-day-status { color: var(--color-muted); margin-top: 2px; } +.oil-day.past { background: #f5f5f5; color: #999; } +.oil-day.future { + background: linear-gradient(135deg, #1677ff 0%, #4096ff 100%); + color: #fff; +} +.oil-day.future .oil-day-status { color: rgba(255,255,255,.85); }