fix: concurrent cache miss, SVG output, narrowed error handling, format
- Fix integration data cache: check pending promise before TTL to prevent returning undefined on concurrent cold-cache access - Add concurrent-miss test (two parallel callers, one fetch) - SVG sanitizer: extract <svg> from DOMPurify output to strip residual HTML wrapper - Narrow safeRevalidateTag catch: log unexpected errors, silence only known "outside request scope" messages - Run oxfmt across all packages (206 files formatted)
This commit is contained in:
206 files changed
+7952
-6722
No files matched your search
@@ -12,15 +12,17 @@ import { cacheTags } from "./cache-tags";
|
||||
import { invalidateIntegrationDataCache } from "./integration-data-cache";
|
||||
|
||||
// ponytail: revalidateTag throws outside Next.js request context (tests, tasks, websocket).
|
||||
// Ceiling: if Next.js context detection changes, update the try-catch.
|
||||
// Ceiling: if Next.js context detection changes, update the require/catch.
|
||||
const safeRevalidateTag = (tag: string) => {
|
||||
try {
|
||||
// Dynamic import avoidance — revalidateTag is only available within Next.js runtime.
|
||||
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||
const { revalidateTag } = require("next/cache") as typeof import("next/cache");
|
||||
revalidateTag(tag, "max");
|
||||
} catch {
|
||||
// Not in a Next.js request context — no-op
|
||||
} catch (error) {
|
||||
const msg = error instanceof Error ? error.message : "";
|
||||
if (!msg.includes("static generation") && !msg.includes("was called outside a request scope")) {
|
||||
console.warn(`[cache-invalidation] revalidateTag("${tag}") failed:`, msg);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -63,6 +63,26 @@ describe("getCachedIntegrationData", () => {
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
test("concurrent cold-cache calls coalesce into one fetch, never return undefined", async () => {
|
||||
let resolveOuter!: (v: { value: number }) => void;
|
||||
const fetcher = vi.fn(
|
||||
() =>
|
||||
new Promise<{ value: number }>((resolve) => {
|
||||
resolveOuter = resolve;
|
||||
}),
|
||||
);
|
||||
|
||||
const p1 = getCachedIntegrationData("integration-a", "widget:concurrent", fetcher);
|
||||
const p2 = getCachedIntegrationData("integration-a", "widget:concurrent", fetcher);
|
||||
|
||||
resolveOuter({ value: 42 });
|
||||
|
||||
const [r1, r2] = await Promise.all([p1, p2]);
|
||||
expect(r1).toEqual({ value: 42 });
|
||||
expect(r2).toEqual({ value: 42 });
|
||||
expect(fetcher).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test("invalidates all cache entries for an integration", async () => {
|
||||
const fetcherOne = vi.fn(async () => ({ value: "one" }));
|
||||
const fetcherTwo = vi.fn(async () => ({ value: "two" }));
|
||||
|
||||
@@ -31,12 +31,12 @@ export const getCachedIntegrationData = async <T>(
|
||||
const now = Date.now();
|
||||
|
||||
if (existing) {
|
||||
if (now - existing.timestamp < ttlMs) {
|
||||
return existing.data;
|
||||
}
|
||||
if (existing.pending) {
|
||||
return existing.pending;
|
||||
}
|
||||
if (existing.timestamp > 0 && now - existing.timestamp < ttlMs) {
|
||||
return existing.data;
|
||||
}
|
||||
}
|
||||
|
||||
const pending = fetcher()
|
||||
|
||||
@@ -101,9 +101,7 @@ describe("patchmonRouter.getStats access control", () => {
|
||||
});
|
||||
const caller = createCaller(db, null);
|
||||
|
||||
await expect(caller.getStats({ integrationId })).rejects.toThrow(
|
||||
new TRPCError({ code: "UNAUTHORIZED" }),
|
||||
);
|
||||
await expect(caller.getStats({ integrationId })).rejects.toThrow(new TRPCError({ code: "UNAUTHORIZED" }));
|
||||
});
|
||||
|
||||
test("should throw FORBIDDEN for authenticated users without board or integration access", async () => {
|
||||
|
||||
@@ -11,17 +11,17 @@ export const coolifyRouter = createTRPCRouter({
|
||||
return await settleIntegrationQueries(
|
||||
ctx.integrations,
|
||||
async (integration) => {
|
||||
const innerHandler = coolifyRequestHandler.handler(integration, {});
|
||||
const { data, timestamp } = await innerHandler.getDataAsync();
|
||||
const innerHandler = coolifyRequestHandler.handler(integration, {});
|
||||
const { data, timestamp } = await innerHandler.getDataAsync();
|
||||
|
||||
return {
|
||||
integrationId: integration.id,
|
||||
integrationName: integration.name,
|
||||
integrationUrl: integration.url,
|
||||
instanceInfo: data,
|
||||
updatedAt: timestamp,
|
||||
};
|
||||
},
|
||||
return {
|
||||
integrationId: integration.id,
|
||||
integrationName: integration.name,
|
||||
integrationUrl: integration.url,
|
||||
instanceInfo: data,
|
||||
updatedAt: timestamp,
|
||||
};
|
||||
},
|
||||
{ queryKey: integrationQueryKey("coolify", "getInstancesInfo") },
|
||||
);
|
||||
}),
|
||||
|
||||
@@ -23,12 +23,12 @@ export const dnsHoleRouter = createTRPCRouter({
|
||||
return await settleIntegrationQueries(
|
||||
ctx.integrations,
|
||||
async (integration) => {
|
||||
const { data, timestamp } = await dnsHoleRequestHandler.handler(integration, {}).getDataAsync();
|
||||
return {
|
||||
integration: { id: integration.id, name: integration.name, kind: integration.kind, updatedAt: timestamp },
|
||||
summary: data,
|
||||
};
|
||||
},
|
||||
const { data, timestamp } = await dnsHoleRequestHandler.handler(integration, {}).getDataAsync();
|
||||
return {
|
||||
integration: { id: integration.id, name: integration.name, kind: integration.kind, updatedAt: timestamp },
|
||||
summary: data,
|
||||
};
|
||||
},
|
||||
{ queryKey: integrationQueryKey("dns-hole", "summary") },
|
||||
);
|
||||
}),
|
||||
|
||||
@@ -28,14 +28,18 @@ export const downloadsRouter = createTRPCRouter({
|
||||
return await settleIntegrationQueries(
|
||||
ctx.integrations,
|
||||
async (integration) => {
|
||||
const innerHandler = downloadClientRequestHandler.handler(integration, { limit: input.limitPerIntegration });
|
||||
const { data, timestamp } = await innerHandler.getDataAsync();
|
||||
return {
|
||||
integration: { id: integration.id, name: integration.name, kind: integration.kind, updatedAt: timestamp },
|
||||
data,
|
||||
};
|
||||
},
|
||||
{ queryKey: integrationQueryKey("downloads", "getJobsAndStatuses", { limitPerIntegration: input.limitPerIntegration }) },
|
||||
const innerHandler = downloadClientRequestHandler.handler(integration, { limit: input.limitPerIntegration });
|
||||
const { data, timestamp } = await innerHandler.getDataAsync();
|
||||
return {
|
||||
integration: { id: integration.id, name: integration.name, kind: integration.kind, updatedAt: timestamp },
|
||||
data,
|
||||
};
|
||||
},
|
||||
{
|
||||
queryKey: integrationQueryKey("downloads", "getJobsAndStatuses", {
|
||||
limitPerIntegration: input.limitPerIntegration,
|
||||
}),
|
||||
},
|
||||
);
|
||||
}),
|
||||
pause: protectedProcedure
|
||||
|
||||
@@ -24,18 +24,21 @@ const queryFirewall = <
|
||||
settleIntegrationQueries(
|
||||
ctx.integrations,
|
||||
async (integration) => {
|
||||
const { data, timestamp } = await handler.handler(integration, {}).getDataAsync();
|
||||
return {
|
||||
integration: { id: integration.id, name: integration.name, kind: integration.kind, updatedAt: timestamp },
|
||||
summary: data as Awaited<ReturnType<ReturnType<THandler["handler"]>["getDataAsync"]>>["data"],
|
||||
};
|
||||
},
|
||||
const { data, timestamp } = await handler.handler(integration, {}).getDataAsync();
|
||||
return {
|
||||
integration: { id: integration.id, name: integration.name, kind: integration.kind, updatedAt: timestamp },
|
||||
summary: data as Awaited<ReturnType<ReturnType<THandler["handler"]>["getDataAsync"]>>["data"],
|
||||
};
|
||||
},
|
||||
{ queryKey },
|
||||
),
|
||||
);
|
||||
|
||||
export const firewallRouter = createTRPCRouter({
|
||||
getFirewallCpuStatus: queryFirewall(firewallCpuRequestHandler, integrationQueryKey("firewall", "getFirewallCpuStatus")),
|
||||
getFirewallCpuStatus: queryFirewall(
|
||||
firewallCpuRequestHandler,
|
||||
integrationQueryKey("firewall", "getFirewallCpuStatus"),
|
||||
),
|
||||
getFirewallInterfacesStatus: queryFirewall(
|
||||
firewallInterfacesRequestHandler,
|
||||
integrationQueryKey("firewall", "getFirewallInterfacesStatus"),
|
||||
|
||||
@@ -29,14 +29,14 @@ export const healthMonitoringRouter = createTRPCRouter({
|
||||
return await settleIntegrationQueries(
|
||||
ctx.integrations,
|
||||
async (integration) => {
|
||||
const { data, timestamp } = await systemInfoRequestHandler.handler(integration, {}).getDataAsync();
|
||||
return {
|
||||
integrationId: integration.id,
|
||||
integrationName: integration.name,
|
||||
healthInfo: data,
|
||||
updatedAt: timestamp,
|
||||
};
|
||||
},
|
||||
const { data, timestamp } = await systemInfoRequestHandler.handler(integration, {}).getDataAsync();
|
||||
return {
|
||||
integrationId: integration.id,
|
||||
integrationName: integration.name,
|
||||
healthInfo: data,
|
||||
updatedAt: timestamp,
|
||||
};
|
||||
},
|
||||
{ queryKey: integrationQueryKey("health-monitoring", "getSystemHealthStatus") },
|
||||
);
|
||||
}),
|
||||
|
||||
@@ -20,14 +20,14 @@ export const indexerManagerRouter = createTRPCRouter({
|
||||
return await settleIntegrationQueries(
|
||||
ctx.integrations,
|
||||
async (integration) => {
|
||||
const innerHandler = indexerManagerRequestHandler.handler(integration, {});
|
||||
const { data: indexers } = await innerHandler.getDataAsync();
|
||||
const innerHandler = indexerManagerRequestHandler.handler(integration, {});
|
||||
const { data: indexers } = await innerHandler.getDataAsync();
|
||||
|
||||
return {
|
||||
integrationId: integration.id,
|
||||
indexers,
|
||||
};
|
||||
},
|
||||
return {
|
||||
integrationId: integration.id,
|
||||
indexers,
|
||||
};
|
||||
},
|
||||
{ queryKey: integrationQueryKey("indexer-manager", "getIndexersStatus") },
|
||||
);
|
||||
}),
|
||||
|
||||
@@ -12,19 +12,19 @@ export const mediaReleaseRouter = createTRPCRouter({
|
||||
const results = await settleIntegrationQueries(
|
||||
ctx.integrations,
|
||||
async (integration) => {
|
||||
const innerHandler = mediaReleaseRequestHandler.handler(integration, {});
|
||||
const { data, timestamp } = await innerHandler.getDataAsync();
|
||||
const innerHandler = mediaReleaseRequestHandler.handler(integration, {});
|
||||
const { data, timestamp } = await innerHandler.getDataAsync();
|
||||
|
||||
return {
|
||||
integration: {
|
||||
id: integration.id,
|
||||
name: integration.name,
|
||||
kind: integration.kind,
|
||||
updatedAt: timestamp,
|
||||
},
|
||||
releases: data,
|
||||
};
|
||||
},
|
||||
return {
|
||||
integration: {
|
||||
id: integration.id,
|
||||
name: integration.name,
|
||||
kind: integration.kind,
|
||||
updatedAt: timestamp,
|
||||
},
|
||||
releases: data,
|
||||
};
|
||||
},
|
||||
{ queryKey: integrationQueryKey("media-release", "getMediaReleases") },
|
||||
);
|
||||
return results.flatMap((result) =>
|
||||
|
||||
@@ -29,9 +29,9 @@ export const mediaRequestsRouter = createTRPCRouter({
|
||||
const results = await settleIntegrationQueries(
|
||||
ctx.integrations,
|
||||
async (integration) => {
|
||||
const { data } = await mediaRequestListRequestHandler.handler(integration, input).getDataAsync();
|
||||
return { integration: { id: integration.id, name: integration.name, kind: integration.kind }, data };
|
||||
},
|
||||
const { data } = await mediaRequestListRequestHandler.handler(integration, input).getDataAsync();
|
||||
return { integration: { id: integration.id, name: integration.name, kind: integration.kind }, data };
|
||||
},
|
||||
{ queryKey: integrationQueryKey("media-requests", "getLatestRequests", input) },
|
||||
);
|
||||
return results
|
||||
@@ -65,9 +65,9 @@ export const mediaRequestsRouter = createTRPCRouter({
|
||||
const results = await settleIntegrationQueries(
|
||||
ctx.integrations,
|
||||
async (integration) => {
|
||||
const { data } = await mediaRequestStatsRequestHandler.handler(integration, {}).getDataAsync();
|
||||
return { integration: { id: integration.id, name: integration.name, kind: integration.kind }, data };
|
||||
},
|
||||
const { data } = await mediaRequestStatsRequestHandler.handler(integration, {}).getDataAsync();
|
||||
return { integration: { id: integration.id, name: integration.name, kind: integration.kind }, data };
|
||||
},
|
||||
{ queryKey: integrationQueryKey("media-requests", "getStats") },
|
||||
);
|
||||
return {
|
||||
|
||||
@@ -26,12 +26,16 @@ export const mediaServerRouter = createTRPCRouter({
|
||||
return await settleIntegrationQueries(
|
||||
ctx.integrations,
|
||||
async (integration) => {
|
||||
const { data } = await mediaServerRequestHandler
|
||||
.handler(integration, { showOnlyPlaying: input.showOnlyPlaying })
|
||||
.getDataAsync();
|
||||
return { integrationId: integration.id, integrationKind: integration.kind, sessions: data };
|
||||
},
|
||||
{ queryKey: integrationQueryKey("media-server", "getCurrentStreams", { showOnlyPlaying: input.showOnlyPlaying }) },
|
||||
const { data } = await mediaServerRequestHandler
|
||||
.handler(integration, { showOnlyPlaying: input.showOnlyPlaying })
|
||||
.getDataAsync();
|
||||
return { integrationId: integration.id, integrationKind: integration.kind, sessions: data };
|
||||
},
|
||||
{
|
||||
queryKey: integrationQueryKey("media-server", "getCurrentStreams", {
|
||||
showOnlyPlaying: input.showOnlyPlaying,
|
||||
}),
|
||||
},
|
||||
);
|
||||
}),
|
||||
});
|
||||
@@ -12,19 +12,19 @@ export const networkControllerRouter = createTRPCRouter({
|
||||
return await settleIntegrationQueries(
|
||||
ctx.integrations,
|
||||
async (integration) => {
|
||||
const innerHandler = networkControllerRequestHandler.handler(integration, {});
|
||||
const { data, timestamp } = await innerHandler.getDataAsync();
|
||||
const innerHandler = networkControllerRequestHandler.handler(integration, {});
|
||||
const { data, timestamp } = await innerHandler.getDataAsync();
|
||||
|
||||
return {
|
||||
integration: {
|
||||
id: integration.id,
|
||||
name: integration.name,
|
||||
kind: integration.kind,
|
||||
},
|
||||
summary: data,
|
||||
updatedAt: timestamp,
|
||||
};
|
||||
},
|
||||
return {
|
||||
integration: {
|
||||
id: integration.id,
|
||||
name: integration.name,
|
||||
kind: integration.kind,
|
||||
},
|
||||
summary: data,
|
||||
updatedAt: timestamp,
|
||||
};
|
||||
},
|
||||
{ queryKey: integrationQueryKey("network-controller", "summary") },
|
||||
);
|
||||
}),
|
||||
|
||||
@@ -16,19 +16,19 @@ export const notificationsRouter = createTRPCRouter({
|
||||
return await settleIntegrationQueries(
|
||||
ctx.integrations,
|
||||
async (integration) => {
|
||||
const innerHandler = notificationsRequestHandler.handler(integration, {});
|
||||
const { data, timestamp } = await innerHandler.getDataAsync();
|
||||
const innerHandler = notificationsRequestHandler.handler(integration, {});
|
||||
const { data, timestamp } = await innerHandler.getDataAsync();
|
||||
|
||||
return {
|
||||
integration: {
|
||||
id: integration.id,
|
||||
name: integration.name,
|
||||
kind: integration.kind,
|
||||
updatedAt: timestamp,
|
||||
},
|
||||
data,
|
||||
};
|
||||
},
|
||||
return {
|
||||
integration: {
|
||||
id: integration.id,
|
||||
name: integration.name,
|
||||
kind: integration.kind,
|
||||
updatedAt: timestamp,
|
||||
},
|
||||
data,
|
||||
};
|
||||
},
|
||||
{ queryKey: integrationQueryKey("notifications", "getNotifications") },
|
||||
);
|
||||
}),
|
||||
|
||||
@@ -11,17 +11,17 @@ export const speedtestTrackerRouter = createTRPCRouter({
|
||||
return await settleIntegrationQueries(
|
||||
ctx.integrations,
|
||||
async (integration) => {
|
||||
const innerHandler = speedtestTrackerRequestHandler.handler(integration, {});
|
||||
const { data, timestamp } = await innerHandler.getDataAsync();
|
||||
const innerHandler = speedtestTrackerRequestHandler.handler(integration, {});
|
||||
const { data, timestamp } = await innerHandler.getDataAsync();
|
||||
|
||||
return {
|
||||
integrationId: integration.id,
|
||||
integrationName: integration.name,
|
||||
integrationUrl: integration.url,
|
||||
dashboard: data,
|
||||
updatedAt: timestamp,
|
||||
};
|
||||
},
|
||||
return {
|
||||
integrationId: integration.id,
|
||||
integrationName: integration.name,
|
||||
integrationUrl: integration.url,
|
||||
dashboard: data,
|
||||
updatedAt: timestamp,
|
||||
};
|
||||
},
|
||||
{ queryKey: integrationQueryKey("speedtest-tracker", "getDashboard") },
|
||||
);
|
||||
}),
|
||||
|
||||
@@ -9,17 +9,17 @@ export const tracearrRouter = createTRPCRouter({
|
||||
return await settleIntegrationQueries(
|
||||
ctx.integrations,
|
||||
async (integration) => {
|
||||
const innerHandler = tracearrRequestHandler.handler(integration, {});
|
||||
const { data, timestamp } = await innerHandler.getDataAsync();
|
||||
const innerHandler = tracearrRequestHandler.handler(integration, {});
|
||||
const { data, timestamp } = await innerHandler.getDataAsync();
|
||||
|
||||
return {
|
||||
integrationId: integration.id,
|
||||
integrationName: integration.name,
|
||||
integrationUrl: integration.url,
|
||||
dashboard: data,
|
||||
updatedAt: timestamp,
|
||||
};
|
||||
},
|
||||
return {
|
||||
integrationId: integration.id,
|
||||
integrationName: integration.name,
|
||||
integrationUrl: integration.url,
|
||||
dashboard: data,
|
||||
updatedAt: timestamp,
|
||||
};
|
||||
},
|
||||
{ queryKey: integrationQueryKey("tracearr", "getDashboard") },
|
||||
);
|
||||
}),
|
||||
|
||||
@@ -18,17 +18,17 @@ export const traefikRouter = createTRPCRouter({
|
||||
return await settleIntegrationQueries(
|
||||
ctx.integrations,
|
||||
async (integration) => {
|
||||
const innerHandler = traefikRequestHandler.handler(integration, {});
|
||||
const { data, timestamp } = await innerHandler.getDataAsync();
|
||||
const innerHandler = traefikRequestHandler.handler(integration, {});
|
||||
const { data, timestamp } = await innerHandler.getDataAsync();
|
||||
|
||||
return {
|
||||
integrationId: integration.id,
|
||||
integrationName: integration.name,
|
||||
integrationUrl: integration.url,
|
||||
dashboard: data,
|
||||
updatedAt: timestamp,
|
||||
};
|
||||
},
|
||||
return {
|
||||
integrationId: integration.id,
|
||||
integrationName: integration.name,
|
||||
integrationUrl: integration.url,
|
||||
dashboard: data,
|
||||
updatedAt: timestamp,
|
||||
};
|
||||
},
|
||||
{ queryKey: integrationQueryKey("traefik", "getDashboard") },
|
||||
);
|
||||
}),
|
||||
|
||||
@@ -42,21 +42,21 @@ export const umamiRouter = createTRPCRouter({
|
||||
return await settleIntegrationQueries(
|
||||
ctx.integrations,
|
||||
async (integration) => {
|
||||
const innerHandler = umamiRequestHandler.handler(integration, {
|
||||
websiteId: input.websiteId,
|
||||
timeFrame: input.timeFrame,
|
||||
eventName: input.eventName,
|
||||
});
|
||||
const { data, timestamp } = await innerHandler.getDataAsync();
|
||||
const innerHandler = umamiRequestHandler.handler(integration, {
|
||||
websiteId: input.websiteId,
|
||||
timeFrame: input.timeFrame,
|
||||
eventName: input.eventName,
|
||||
});
|
||||
const { data, timestamp } = await innerHandler.getDataAsync();
|
||||
|
||||
return {
|
||||
integrationId: integration.id,
|
||||
integrationName: integration.name,
|
||||
integrationUrl: integration.url,
|
||||
visitorStats: data,
|
||||
updatedAt: timestamp,
|
||||
};
|
||||
},
|
||||
return {
|
||||
integrationId: integration.id,
|
||||
integrationName: integration.name,
|
||||
integrationUrl: integration.url,
|
||||
visitorStats: data,
|
||||
updatedAt: timestamp,
|
||||
};
|
||||
},
|
||||
{
|
||||
queryKey: integrationQueryKey("umami", "getVisitorStats", {
|
||||
websiteId: input.websiteId,
|
||||
|
||||
@@ -12,17 +12,17 @@ export const upsRouter = createTRPCRouter({
|
||||
return await settleIntegrationQueries(
|
||||
ctx.integrations,
|
||||
async (integration) => {
|
||||
const innerHandler = upsSummariesRequestHandler.handler(integration, {});
|
||||
const { data, timestamp } = await innerHandler.getDataAsync();
|
||||
const innerHandler = upsSummariesRequestHandler.handler(integration, {});
|
||||
const { data, timestamp } = await innerHandler.getDataAsync();
|
||||
|
||||
return {
|
||||
integrationId: integration.id,
|
||||
integrationName: integration.name,
|
||||
integrationUrl: integration.url,
|
||||
summaries: data,
|
||||
updatedAt: timestamp,
|
||||
};
|
||||
},
|
||||
return {
|
||||
integrationId: integration.id,
|
||||
integrationName: integration.name,
|
||||
integrationUrl: integration.url,
|
||||
summaries: data,
|
||||
updatedAt: timestamp,
|
||||
};
|
||||
},
|
||||
{ queryKey: integrationQueryKey("ups", "getSummaries") },
|
||||
);
|
||||
}),
|
||||
|
||||
@@ -11,17 +11,17 @@ export const uptimeKumaRouter = createTRPCRouter({
|
||||
return await settleIntegrationQueries(
|
||||
ctx.integrations,
|
||||
async (integration) => {
|
||||
const innerHandler = uptimeKumaRequestHandler.handler(integration, {});
|
||||
const { data, timestamp } = await innerHandler.getDataAsync();
|
||||
const innerHandler = uptimeKumaRequestHandler.handler(integration, {});
|
||||
const { data, timestamp } = await innerHandler.getDataAsync();
|
||||
|
||||
return {
|
||||
integrationId: integration.id,
|
||||
integrationName: integration.name,
|
||||
integrationUrl: integration.url,
|
||||
dashboard: data,
|
||||
updatedAt: timestamp,
|
||||
};
|
||||
},
|
||||
return {
|
||||
integrationId: integration.id,
|
||||
integrationName: integration.name,
|
||||
integrationUrl: integration.url,
|
||||
dashboard: data,
|
||||
updatedAt: timestamp,
|
||||
};
|
||||
},
|
||||
{ queryKey: integrationQueryKey("uptime-kuma", "getDashboard") },
|
||||
);
|
||||
}),
|
||||
|
||||
@@ -12,17 +12,17 @@ export const vpnRouter = createTRPCRouter({
|
||||
return await settleIntegrationQueries(
|
||||
ctx.integrations,
|
||||
async (integration) => {
|
||||
const { data, timestamp } = await vpnSummaryHandler.handler(integration, {}).getDataAsync();
|
||||
return {
|
||||
integration: {
|
||||
id: integration.id,
|
||||
name: integration.name,
|
||||
kind: integration.kind,
|
||||
updatedAt: timestamp,
|
||||
},
|
||||
summary: data,
|
||||
};
|
||||
},
|
||||
const { data, timestamp } = await vpnSummaryHandler.handler(integration, {}).getDataAsync();
|
||||
return {
|
||||
integration: {
|
||||
id: integration.id,
|
||||
name: integration.name,
|
||||
kind: integration.kind,
|
||||
updatedAt: timestamp,
|
||||
},
|
||||
summary: data,
|
||||
};
|
||||
},
|
||||
{ queryKey: integrationQueryKey("vpn", "getSummaries") },
|
||||
);
|
||||
}),
|
||||
|
||||
Reference in new issue
Block a user