refactor: extract signals filter builder, add ESLint 10 config, fix low-hanging issues
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import pool from '@/lib/db';
|
||||
import { type NextRequest, NextResponse } from 'next/server';
|
||||
|
||||
import { withAuth } from '@/lib/apiHelpers';
|
||||
import pool from '@/lib/db';
|
||||
|
||||
export const PUT = withAuth(async (req: NextRequest, { params }) => {
|
||||
const { id } = await params;
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import { NextResponse } from 'next/server';
|
||||
import pool from '@/lib/db';
|
||||
|
||||
import type { AlertConfig, TriggeredAlert } from '@/lib/types';
|
||||
|
||||
import { withAuth } from '@/lib/apiHelpers';
|
||||
import pool from '@/lib/db';
|
||||
import { getServerLocaleMap } from '@/lib/localeServer';
|
||||
import { resolveName } from '@/lib/localization';
|
||||
import type { AlertConfig, TriggeredAlert } from '@/lib/types';
|
||||
|
||||
export const GET = withAuth(async () => {
|
||||
const alertsResult = await pool.query<AlertConfig>(
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import pool from '@/lib/db';
|
||||
import { type NextRequest, NextResponse } from 'next/server';
|
||||
|
||||
import { withAuth } from '@/lib/apiHelpers';
|
||||
import pool from '@/lib/db';
|
||||
|
||||
export const GET = withAuth(async () => {
|
||||
const result = await pool.query('SELECT * FROM alerts ORDER BY created_at DESC');
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import pool from '@/lib/db';
|
||||
import { type NextRequest, NextResponse } from 'next/server';
|
||||
|
||||
import { withAuth } from '@/lib/apiHelpers';
|
||||
import pool from '@/lib/db';
|
||||
|
||||
export const PUT = withAuth(async (req: NextRequest, { params }) => {
|
||||
const { id } = await params;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import pool from '@/lib/db';
|
||||
import { type NextRequest, NextResponse } from 'next/server';
|
||||
|
||||
import { withAuth } from '@/lib/apiHelpers';
|
||||
import pool from '@/lib/db';
|
||||
|
||||
export const GET = withAuth(async () => {
|
||||
const result = await pool.query('SELECT * FROM charts ORDER BY pos_y ASC, pos_x ASC');
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import pool from '@/lib/db';
|
||||
import { type NextRequest, NextResponse } from 'next/server';
|
||||
|
||||
import { withAuth } from '@/lib/apiHelpers';
|
||||
import pool from '@/lib/db';
|
||||
|
||||
interface CircuitNetwork {
|
||||
green: Record<string, number>;
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { getSessionBoundaries } from '@/lib/sessions';
|
||||
import { type NextRequest, NextResponse } from 'next/server';
|
||||
|
||||
import { withAuth } from '@/lib/apiHelpers';
|
||||
import { getSessionBoundaries } from '@/lib/sessions';
|
||||
|
||||
export const GET = withAuth(async (req: NextRequest) => {
|
||||
const p = req.nextUrl.searchParams;
|
||||
const from = p.get('from') ? new Date(p.get('from')!) : new Date(Date.now() - 86_400_000);
|
||||
const to = p.get('to') ? new Date(p.get('to')!) : new Date();
|
||||
const fromVal = p.get('from');
|
||||
const toVal = p.get('to');
|
||||
const from = fromVal ? new Date(fromVal) : new Date(Date.now() - 86_400_000);
|
||||
const to = toVal ? new Date(toVal) : new Date();
|
||||
const boundaries = await getSessionBoundaries(from, to);
|
||||
return NextResponse.json(boundaries);
|
||||
});
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { type NextRequest, NextResponse } from 'next/server';
|
||||
|
||||
import { withAuth, buildItemFilter } from '@/lib/apiHelpers';
|
||||
import pool from '@/lib/db';
|
||||
import { withAuth } from '@/lib/apiHelpers';
|
||||
import { getServerLocaleMap } from '@/lib/localeServer';
|
||||
import { matchKeys } from '@/lib/localization';
|
||||
|
||||
export const GET = withAuth(async (req: NextRequest) => {
|
||||
const p = req.nextUrl.searchParams;
|
||||
@@ -14,59 +13,30 @@ export const GET = withAuth(async (req: NextRequest) => {
|
||||
const to = p.get('to');
|
||||
const useRegex = p.get('regex') === 'true';
|
||||
const orderBy = p.get('order_by') ?? 'value_asc';
|
||||
const limit = p.get('limit') ? parseInt(p.get('limit')!, 10) : null;
|
||||
const limitStr = p.get('limit');
|
||||
const limit = limitStr ? parseInt(limitStr, 10) : null;
|
||||
|
||||
const conditions: string[] = [];
|
||||
const values: unknown[] = [];
|
||||
let i = 1;
|
||||
const param = { current: 1 };
|
||||
|
||||
if (combinators.length > 0) {
|
||||
conditions.push(`combinator = ANY($${i++})`);
|
||||
conditions.push(`combinator = ANY($${param.current++})`);
|
||||
values.push(combinators);
|
||||
}
|
||||
|
||||
if (itemsWhitelist.length > 0) {
|
||||
if (useRegex) {
|
||||
const localeMap = getServerLocaleMap();
|
||||
const localeKeys = [...new Set(itemsWhitelist.flatMap((p) => matchKeys(p, localeMap)))];
|
||||
const sqlPattern = itemsWhitelist.map((p) => `(${p})`).join('|');
|
||||
const orConds = [`item_key ~* $${i++}`];
|
||||
values.push(sqlPattern);
|
||||
if (localeKeys.length > 0) {
|
||||
orConds.push(`item_key = ANY($${i++})`);
|
||||
values.push(localeKeys);
|
||||
}
|
||||
conditions.push(`(${orConds.join(' OR ')})`);
|
||||
} else {
|
||||
conditions.push(`item_key = ANY($${i++})`);
|
||||
values.push(itemsWhitelist);
|
||||
}
|
||||
}
|
||||
const wlClause = buildItemFilter(itemsWhitelist, useRegex, true, values, param);
|
||||
if (wlClause) conditions.push(wlClause);
|
||||
|
||||
if (itemsBlacklist.length > 0) {
|
||||
if (useRegex) {
|
||||
const localeMap = getServerLocaleMap();
|
||||
const localeKeys = [...new Set(itemsBlacklist.flatMap((p) => matchKeys(p, localeMap)))];
|
||||
const sqlPattern = itemsBlacklist.map((p) => `(${p})`).join('|');
|
||||
const andConds = [`item_key !~* $${i++}`];
|
||||
values.push(sqlPattern);
|
||||
if (localeKeys.length > 0) {
|
||||
andConds.push(`item_key != ALL($${i++})`);
|
||||
values.push(localeKeys);
|
||||
}
|
||||
conditions.push(`(${andConds.join(' AND ')})`);
|
||||
} else {
|
||||
conditions.push(`item_key != ALL($${i++})`);
|
||||
values.push(itemsBlacklist);
|
||||
}
|
||||
}
|
||||
const blClause = buildItemFilter(itemsBlacklist, useRegex, false, values, param);
|
||||
if (blClause) conditions.push(blClause);
|
||||
|
||||
if (from) {
|
||||
conditions.push(`real_time >= $${i++}`);
|
||||
conditions.push(`real_time >= $${param.current++}`);
|
||||
values.push(new Date(from));
|
||||
}
|
||||
if (to) {
|
||||
conditions.push(`real_time <= $${i++}`);
|
||||
conditions.push(`real_time <= $${param.current++}`);
|
||||
values.push(new Date(to));
|
||||
}
|
||||
|
||||
@@ -83,46 +53,18 @@ export const GET = withAuth(async (req: NextRequest) => {
|
||||
if ((orderBy === 'delta_asc' || orderBy === 'delta_desc') && limit !== null) {
|
||||
const baseConditions: string[] = [];
|
||||
const baseValues: unknown[] = [];
|
||||
let j = 1;
|
||||
const baseParam = { current: 1 };
|
||||
|
||||
if (combinators.length > 0) {
|
||||
baseConditions.push(`combinator = ANY($${j++})`);
|
||||
baseConditions.push(`combinator = ANY($${baseParam.current++})`);
|
||||
baseValues.push(combinators);
|
||||
}
|
||||
if (itemsWhitelist.length > 0) {
|
||||
if (useRegex) {
|
||||
const localeMap = getServerLocaleMap();
|
||||
const localeKeys = [...new Set(itemsWhitelist.flatMap((p) => matchKeys(p, localeMap)))];
|
||||
const sqlPattern = itemsWhitelist.map((p) => `(${p})`).join('|');
|
||||
const orConds = [`item_key ~* $${j++}`];
|
||||
baseValues.push(sqlPattern);
|
||||
if (localeKeys.length > 0) {
|
||||
orConds.push(`item_key = ANY($${j++})`);
|
||||
baseValues.push(localeKeys);
|
||||
}
|
||||
baseConditions.push(`(${orConds.join(' OR ')})`);
|
||||
} else {
|
||||
baseConditions.push(`item_key = ANY($${j++})`);
|
||||
baseValues.push(itemsWhitelist);
|
||||
}
|
||||
}
|
||||
if (itemsBlacklist.length > 0) {
|
||||
if (useRegex) {
|
||||
const localeMap = getServerLocaleMap();
|
||||
const localeKeys = [...new Set(itemsBlacklist.flatMap((p) => matchKeys(p, localeMap)))];
|
||||
const sqlPattern = itemsBlacklist.map((p) => `(${p})`).join('|');
|
||||
const andConds = [`item_key !~* $${j++}`];
|
||||
baseValues.push(sqlPattern);
|
||||
if (localeKeys.length > 0) {
|
||||
andConds.push(`item_key != ALL($${j++})`);
|
||||
baseValues.push(localeKeys);
|
||||
}
|
||||
baseConditions.push(`(${andConds.join(' AND ')})`);
|
||||
} else {
|
||||
baseConditions.push(`item_key != ALL($${j++})`);
|
||||
baseValues.push(itemsBlacklist);
|
||||
}
|
||||
}
|
||||
|
||||
const wlBase = buildItemFilter(itemsWhitelist, useRegex, true, baseValues, baseParam);
|
||||
if (wlBase) baseConditions.push(wlBase);
|
||||
|
||||
const blBase = buildItemFilter(itemsBlacklist, useRegex, false, baseValues, baseParam);
|
||||
if (blBase) baseConditions.push(blBase);
|
||||
|
||||
const baseWhere = baseConditions.length > 0 ? `WHERE ${baseConditions.join(' AND ')}` : '';
|
||||
const baseWhereAnd = baseConditions.length > 0 ? `AND ${baseConditions.join(' AND ')}` : '';
|
||||
@@ -155,25 +97,27 @@ export const GET = withAuth(async (req: NextRequest) => {
|
||||
SELECT combinator, item_key, delta
|
||||
FROM deltas
|
||||
ORDER BY delta ${orderBy === 'delta_asc' ? 'ASC' : 'DESC'}
|
||||
LIMIT $${j}
|
||||
LIMIT $${baseParam.current}
|
||||
`;
|
||||
|
||||
const deltaResult = await pool.query<{ combinator: string; item_key: string; delta: number }>(
|
||||
deltaQuery,
|
||||
[...baseValues, limit],
|
||||
);
|
||||
const deltaResult = await pool.query<{
|
||||
combinator: string;
|
||||
item_key: string;
|
||||
delta: number;
|
||||
}>(deltaQuery, [...baseValues, limit]);
|
||||
|
||||
const top = deltaResult.rows;
|
||||
if (top.length === 0) return NextResponse.json([]);
|
||||
|
||||
const seriesConditions = top.map(
|
||||
(_, idx) => `(combinator = $${i + idx * 2} AND item_key = $${i + idx * 2 + 1})`,
|
||||
(_, idx) =>
|
||||
`(combinator = $${param.current + idx * 2} AND item_key = $${param.current + idx * 2 + 1})`,
|
||||
);
|
||||
const fullWhere = `${where ? where + ' AND' : 'WHERE'} (${seriesConditions.join(' OR ')})`;
|
||||
const orderCase = top
|
||||
.map(
|
||||
(_, idx) =>
|
||||
`WHEN combinator = $${i + idx * 2} AND item_key = $${i + idx * 2 + 1} THEN ${idx}`,
|
||||
`WHEN combinator = $${param.current + idx * 2} AND item_key = $${param.current + idx * 2 + 1} THEN ${idx}`,
|
||||
)
|
||||
.join(' ');
|
||||
const result = await pool.query(
|
||||
@@ -187,7 +131,11 @@ export const GET = withAuth(async (req: NextRequest) => {
|
||||
(orderBy === 'value_asc' || orderBy === 'value_desc' || orderBy === 'abs_desc') &&
|
||||
limit !== null
|
||||
) {
|
||||
const latestVals = await pool.query<{ combinator: string; item_key: string; val: number }>(
|
||||
const latestVals = await pool.query<{
|
||||
combinator: string;
|
||||
item_key: string;
|
||||
val: number;
|
||||
}>(
|
||||
`SELECT DISTINCT ON (combinator, item_key)
|
||||
combinator, item_key, ${valueCol} AS val
|
||||
FROM signals ${where}
|
||||
@@ -205,13 +153,14 @@ export const GET = withAuth(async (req: NextRequest) => {
|
||||
if (top.length === 0) return NextResponse.json([]);
|
||||
|
||||
const seriesConditions = top.map(
|
||||
(_, idx) => `(combinator = $${i + idx * 2} AND item_key = $${i + idx * 2 + 1})`,
|
||||
(_, idx) =>
|
||||
`(combinator = $${param.current + idx * 2} AND item_key = $${param.current + idx * 2 + 1})`,
|
||||
);
|
||||
const fullWhere = `${where ? where + ' AND' : 'WHERE'} (${seriesConditions.join(' OR ')})`;
|
||||
const orderCase = top
|
||||
.map(
|
||||
(_, idx) =>
|
||||
`WHEN combinator = $${i + idx * 2} AND item_key = $${i + idx * 2 + 1} THEN ${idx}`,
|
||||
`WHEN combinator = $${param.current + idx * 2} AND item_key = $${param.current + idx * 2 + 1} THEN ${idx}`,
|
||||
)
|
||||
.join(' ');
|
||||
const result = await pool.query(
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import pool from '@/lib/db';
|
||||
import { type NextRequest, NextResponse } from 'next/server';
|
||||
|
||||
import { withAuth } from '@/lib/apiHelpers';
|
||||
import pool from '@/lib/db';
|
||||
|
||||
export const GET = withAuth(async (req: NextRequest) => {
|
||||
const p = req.nextUrl.searchParams;
|
||||
const combinator = p.get('combinator');
|
||||
const from = p.get('from') ? new Date(p.get('from')!) : new Date(Date.now() - 86_400_000);
|
||||
const to = p.get('to') ? new Date(p.get('to')!) : new Date();
|
||||
const fromVal = p.get('from');
|
||||
const toVal = p.get('to');
|
||||
const from = fromVal ? new Date(fromVal) : new Date(Date.now() - 86_400_000);
|
||||
const to = toVal ? new Date(toVal) : new Date();
|
||||
|
||||
const conditions = ['real_time BETWEEN $1 AND $2'];
|
||||
const values: unknown[] = [from, to];
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
'use client';
|
||||
|
||||
import { useEffect, useState, Suspense } from 'react';
|
||||
import { useSearchParams } from 'next/navigation';
|
||||
import { AppProvider, useApp } from '@/lib/context';
|
||||
import { setToken, fetchAlerts } from '@/lib/api';
|
||||
import { getLocaleMap } from '@/lib/localization';
|
||||
import type { AlertConfig } from '@/lib/types';
|
||||
import { useEffect, useState, Suspense } from 'react';
|
||||
|
||||
import type { LocaleMap } from '@/lib/localization';
|
||||
import TimeRangeSelector from '@/components/TimeRangeSelector';
|
||||
import type { AlertConfig } from '@/lib/types';
|
||||
|
||||
import AlertPanel from '@/components/AlertPanel';
|
||||
import Dashboard from '@/components/Dashboard';
|
||||
import TimeRangeSelector from '@/components/TimeRangeSelector';
|
||||
import { setToken, fetchAlerts } from '@/lib/api';
|
||||
import { AppProvider, useApp } from '@/lib/context';
|
||||
import { getLocaleMap } from '@/lib/localization';
|
||||
|
||||
function AppShell({ alerts }: { alerts: AlertConfig[] }) {
|
||||
const { triggeredAlerts } = useApp();
|
||||
|
||||
Reference in New Issue
Block a user