Main #7
No files matched your search
@@ -0,0 +1,31 @@
|
|||||||
|
FROM oven/bun:1-alpine AS base
|
||||||
|
|
||||||
|
FROM base AS deps
|
||||||
|
WORKDIR /app
|
||||||
|
COPY package.json .
|
||||||
|
RUN bun install
|
||||||
|
|
||||||
|
FROM base AS builder
|
||||||
|
WORKDIR /app
|
||||||
|
ARG NEXT_PUBLIC_API_URL=http://127.0.0.1:3001
|
||||||
|
ENV NEXT_PUBLIC_API_URL=$NEXT_PUBLIC_API_URL
|
||||||
|
COPY --from=deps /app/node_modules ./node_modules
|
||||||
|
COPY . .
|
||||||
|
RUN bun run build
|
||||||
|
|
||||||
|
FROM base AS runner
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
ENV NODE_ENV production
|
||||||
|
ENV NEXT_TELEMETRY_DISABLED 1
|
||||||
|
|
||||||
|
COPY --from=builder /app/public ./public
|
||||||
|
COPY --from=builder /app/.next/standalone ./
|
||||||
|
COPY --from=builder /app/.next/static ./.next/static
|
||||||
|
|
||||||
|
EXPOSE 3000
|
||||||
|
|
||||||
|
ENV PORT 3000
|
||||||
|
ENV HOSTNAME "0.0.0.0"
|
||||||
|
|
||||||
|
CMD ["bun", "run", "server.js"]
|
||||||
@@ -44,21 +44,25 @@ async function populateAppCache(BASE_URL, token, siteUuid) {
|
|||||||
const headers = { 'x-api-key': token, 'Accept': 'application/json' };
|
const headers = { 'x-api-key': token, 'Accept': 'application/json' };
|
||||||
if (siteUuid) headers['x-net-site'] = siteUuid;
|
if (siteUuid) headers['x-net-site'] = siteUuid;
|
||||||
const res = await axios.get(`${BASE_URL}/lookup/applications`, {
|
const res = await axios.get(`${BASE_URL}/lookup/applications`, {
|
||||||
headers, params: { settings_limit: 2000 }, timeout: 8000
|
headers, params: { settings_limit: 5000 }, timeout: 20000
|
||||||
});
|
});
|
||||||
appLookupCache = {};
|
appLookupCache = {};
|
||||||
if (res.data && Array.isArray(res.data.data)) {
|
if (res.data && Array.isArray(res.data.data)) {
|
||||||
res.data.data.forEach(a => {
|
res.data.data.forEach(a => {
|
||||||
if (!a.label || !a.id) return;
|
if (!a.id) return;
|
||||||
|
const label = (a.label || '').trim();
|
||||||
|
if (!label) return;
|
||||||
let domain = null;
|
let domain = null;
|
||||||
if (a.home_page?.url) {
|
if (a.home_page?.url) {
|
||||||
domain = a.home_page.url.replace(/^https?:\/\/(www\.)?/, '').split('/')[0];
|
domain = a.home_page.url.replace(/^https?:\/\/(www\.)?/, '').split('/')[0];
|
||||||
} else if (a.domain_list?.length > 0) {
|
} else if (a.domain_list?.length > 0) {
|
||||||
domain = a.domain_list[0].label;
|
domain = a.domain_list[0].label;
|
||||||
} else {
|
} else {
|
||||||
domain = a.label.toLowerCase();
|
domain = label.toLowerCase();
|
||||||
}
|
}
|
||||||
appLookupCache[a.label.toLowerCase()] = { id: a.id, label: a.label, domain };
|
const entry = { id: a.id, label, domain };
|
||||||
|
appLookupCache[label.toLowerCase()] = entry;
|
||||||
|
if (a.tag) appLookupCache[a.tag.toLowerCase()] = entry;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
console.log(`[AppDetailsDpiHelper] App cache: ${Object.keys(appLookupCache).length} apps`);
|
console.log(`[AppDetailsDpiHelper] App cache: ${Object.keys(appLookupCache).length} apps`);
|
||||||
@@ -92,12 +96,12 @@ async function fetchFromDpiApi(label, agentUuid, timeRange, token, siteUuid) {
|
|||||||
|
|
||||||
const params = {
|
const params = {
|
||||||
filter_interval: timeRangeToMinutes(timeRange),
|
filter_interval: timeRangeToMinutes(timeRange),
|
||||||
filter_applications: `["${appInfo.id}"]`,
|
filter_applications: `[${appInfo.id}]`,
|
||||||
settings_limit: 10000
|
settings_limit: 10000
|
||||||
};
|
};
|
||||||
|
|
||||||
if (agentUuid && agentMapCache?.[agentUuid]) {
|
if (agentUuid && agentMapCache?.[agentUuid]) {
|
||||||
params.filter_agents = `[${agentMapCache[agentUuid]}]`;
|
params.filter_agents = `["${agentMapCache[agentUuid]}"]`;
|
||||||
}
|
}
|
||||||
|
|
||||||
const [dlRes, ulRes] = await Promise.all([
|
const [dlRes, ulRes] = await Promise.all([
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ module.exports = async function appDetailsHandler(req, res, helpers) {
|
|||||||
if (deviceApps.length > 0) {
|
if (deviceApps.length > 0) {
|
||||||
// Pre-load application lookup to resolve default domains
|
// Pre-load application lookup to resolve default domains
|
||||||
const BASE_URL = process.env.NETIFY_INFORMATICS_BASE_URL || 'https://informatics.netify.ai/api/v1';
|
const BASE_URL = process.env.NETIFY_INFORMATICS_BASE_URL || 'https://informatics.netify.ai/api/v1';
|
||||||
if (token && SITE_UUID) {
|
if (token) {
|
||||||
await populateAppCache(BASE_URL, token, SITE_UUID).catch(e => console.warn('[AppDetails] Cache error:', e.message));
|
await populateAppCache(BASE_URL, token, SITE_UUID).catch(e => console.warn('[AppDetails] Cache error:', e.message));
|
||||||
}
|
}
|
||||||
const appMeta = getAppLookupCache()?.[label.toLowerCase()];
|
const appMeta = getAppLookupCache()?.[label.toLowerCase()];
|
||||||
@@ -96,7 +96,7 @@ module.exports = async function appDetailsHandler(req, res, helpers) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ── Step 2: Fall back to DPI API only if MongoDB has ZERO data ────────────
|
// ── Step 2: Fall back to DPI API only if MongoDB has ZERO data ────────────
|
||||||
if (token && SITE_UUID) {
|
if (token) {
|
||||||
const dpiResult = await fetchFromDpiApi(label, agentUuid, req.query.timeRange, token, SITE_UUID);
|
const dpiResult = await fetchFromDpiApi(label, agentUuid, req.query.timeRange, token, SITE_UUID);
|
||||||
if (dpiResult) {
|
if (dpiResult) {
|
||||||
console.log(`[AppDetails] DPI fallback: label=${label} time=${Date.now()-t0}ms`);
|
console.log(`[AppDetails] DPI fallback: label=${label} time=${Date.now()-t0}ms`);
|
||||||
|
|||||||
+2
-7
@@ -6,7 +6,7 @@ import type { NextConfig } from "next";
|
|||||||
|
|
||||||
const nextConfig: NextConfig = {
|
const nextConfig: NextConfig = {
|
||||||
output: "standalone",
|
output: "standalone",
|
||||||
serverExternalPackages: ["mongoose", "better-sqlite3"],
|
serverExternalPackages: ["mongoose"],
|
||||||
experimental: {
|
experimental: {
|
||||||
serverActions: {
|
serverActions: {
|
||||||
allowedOrigins: [
|
allowedOrigins: [
|
||||||
@@ -46,12 +46,7 @@ const nextConfig: NextConfig = {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
async rewrites() {
|
async rewrites() {
|
||||||
return [
|
return [];
|
||||||
{
|
|
||||||
source: '/api/:path*',
|
|
||||||
destination: `${process.env.NEXT_PUBLIC_API_URL || 'http://127.0.0.1:3001'}/api/:path*`,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Generated
-11264
File diff suppressed because it is too large.
Load diff
@@ -27,7 +27,6 @@
|
|||||||
"@types/leaflet": "^1.9.21",
|
"@types/leaflet": "^1.9.21",
|
||||||
"axios": "^1.18.1",
|
"axios": "^1.18.1",
|
||||||
"bcryptjs": "^3.0.3",
|
"bcryptjs": "^3.0.3",
|
||||||
"better-sqlite3": "^12.11.1",
|
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"concurrently": "^10.0.3",
|
"concurrently": "^10.0.3",
|
||||||
"cookie": "^2.0.1",
|
"cookie": "^2.0.1",
|
||||||
|
|||||||
Reference in new issue
Block a user