Skip to content

Commit 6b6ef2f

Browse files
ImLunaHeygabrielelpidio
authored andcommitted
feat: middleware
1 parent d07b88e commit 6b6ef2f

File tree

6 files changed

+272
-14
lines changed

6 files changed

+272
-14
lines changed

package-lock.json

+130
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+4-3
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818
"prepare": "npm run build",
1919
"format": "prettier --write src/*.ts tests/*.ts",
2020
"check-format": "prettier -c src/*.ts tests/*.ts",
21-
"test": "vitest run tests --coverage"
21+
"test": "vitest run tests --coverage",
22+
"test:watch": "vitest tests --coverage --ui"
2223
},
2324
"repository": {
2425
"type": "git",
@@ -49,7 +50,7 @@
4950
"vitest": "^2.1.5"
5051
},
5152
"dependencies": {
52-
"whatwg-fetch": "^3.6.2",
53-
"use-deep-compare": "^1.2.1"
53+
"use-deep-compare": "^1.2.1",
54+
"whatwg-fetch": "^3.6.2"
5455
}
5556
}

src/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
export { log, Logger, LogLevel, type LoggerConfig, type RequestReport } from './logger';
22
export { EndpointType, throttle } from './shared';
3+
export { middleware, config } from './middleware';
34
export * from './platform/base';
45
export * from './config';
56
export { withAxiom, type AxiomRequest, withAxiomNextConfig, withAxiomRouteHandler } from './withAxiom';

src/middleware.ts

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { NextResponse } from 'next/server';
2+
import type { NextFetchEvent, NextRequest } from 'next/server';
3+
import { config as axiomConfig } from './config';
4+
import { EndpointType } from './shared';
5+
6+
const webVitalsEndpoint = axiomConfig.getIngestURL(EndpointType.webVitals);
7+
const logsEndpoint = axiomConfig.getIngestURL(EndpointType.logs);
8+
9+
const headers = {
10+
authorization: 'Bearer ' + axiomConfig.token,
11+
'Content-Type': 'application/json',
12+
};
13+
14+
export async function middleware(request: NextRequest, event: NextFetchEvent): Promise<NextResponse<unknown> | void> {
15+
// If the request is not for axiom, do nothing
16+
// This is a safety check, as users may add a custom matcher
17+
if (!request.nextUrl.pathname.startsWith('/_axiom')) return;
18+
19+
// Web vitals
20+
if (request.nextUrl.pathname.startsWith('/_axiom/web-vitals')) {
21+
// Forward the request to the axiom ingest endpoint
22+
event.waitUntil(
23+
fetch(webVitalsEndpoint, {
24+
body: request.body,
25+
method: 'POST',
26+
headers,
27+
}).catch(console.error)
28+
);
29+
30+
// Return a 204 to the client
31+
return new NextResponse(null, { status: 204 });
32+
}
33+
34+
// Logs
35+
if (request.nextUrl.pathname.startsWith('/_axiom/logs')) {
36+
// Forward the request to the axiom ingest endpoint
37+
event.waitUntil(
38+
fetch(logsEndpoint, {
39+
body: request.body,
40+
method: 'POST',
41+
headers,
42+
}).catch(console.error)
43+
);
44+
45+
// Return a 204 to the client
46+
return new NextResponse(null, { status: 204 });
47+
}
48+
}
49+
50+
export const config = {
51+
matcher: '/_axiom/:path*',
52+
};

src/platform/generic.ts

+15-11
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import { GetServerSidePropsContext, NextApiRequest } from "next";
2-
import { LogEvent } from "../logger";
3-
import { EndpointType } from "../shared";
4-
import type Provider from "./base";
5-
import { isBrowser, isVercel } from "../config";
1+
import { GetServerSidePropsContext, NextApiRequest } from 'next';
2+
import { LogEvent } from '../logger';
3+
import { EndpointType } from '../shared';
4+
import type Provider from './base';
5+
import { isBrowser, isVercel } from '../config';
66

77
// This is the generic config class for all platforms that doesn't have a special
88
// implementation (e.g: vercel, netlify). All config classes extends this one.
@@ -17,6 +17,10 @@ export default class GenericConfig implements Provider {
1717
customEndpoint: string | undefined = process.env.NEXT_PUBLIC_AXIOM_CUSTOM_ENDPOINT;
1818

1919
isEnvVarsSet(): boolean {
20+
if (isBrowser) {
21+
return !!(this.axiomUrl && this.dataset) || !!this.customEndpoint;
22+
}
23+
2024
return !!(this.axiomUrl && this.dataset && this.token) || !!this.customEndpoint;
2125
}
2226

@@ -41,21 +45,21 @@ export default class GenericConfig implements Provider {
4145
}
4246

4347
wrapWebVitalsObject(metrics: any[]): any {
44-
return metrics.map(m => ({
48+
return metrics.map((m) => ({
4549
webVital: m,
4650
_time: new Date().getTime(),
4751
platform: {
4852
environment: this.environment,
4953
source: 'web-vital',
5054
},
51-
source: 'web-vital'
52-
}))
55+
source: 'web-vital',
56+
}));
5357
}
5458

5559
injectPlatformMetadata(logEvent: LogEvent, source: string) {
56-
let key: "platform" | "vercel" | "netlify" = "platform"
60+
let key: 'platform' | 'vercel' | 'netlify' = 'platform';
5761
if (isVercel) {
58-
key = "vercel"
62+
key = 'vercel';
5963
}
6064

6165
logEvent.source = source;
@@ -74,7 +78,7 @@ export default class GenericConfig implements Provider {
7478
commit: process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_SHA,
7579
repo: process.env.NEXT_PUBLIC_VERCEL_GIT_REPO_SLUG,
7680
ref: process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_REF,
77-
}
81+
};
7882
}
7983
}
8084

0 commit comments

Comments
 (0)