@safaricom-mxl/nextjs
Version:
MXL Javascript RUM agent for nextjs
133 lines (128 loc) • 4.63 kB
JavaScript
;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/server.ts
var server_exports = {};
__export(server_exports, {
createRouteHandler: () => createRouteHandler
});
module.exports = __toCommonJS(server_exports);
// src/create-next-route-handler.ts
var import_node_crypto = require("crypto");
var import_server = require("next/server.js");
// src/constants.ts
var SCRIPT_URL = "https://mxl-scripts.apps.ocpthikadev01.safaricom.net/v1";
var DEFAULT_API_URL = "https://mxl-server.apps.ocpthikadev01.safaricom.net";
var SCRIPT_PATH = "/mxl.js";
// src/create-next-route-handler.ts
function getClientHeaders(req) {
const headers = new Headers();
const ip = req.headers.get("cf-connecting-ip") ?? req.headers.get("x-forwarded-for")?.split(",")[0] ?? req.headers.get("x-vercel-forwarded-for");
headers.set("Content-Type", "application/json");
headers.set("mxl-client-id", req.headers.get("mxl-client-id") ?? "");
const origin = req.headers.get("origin") ?? (() => {
const url = new URL(req.url);
return `${url.protocol}//${url.host}`;
})();
headers.set("origin", origin);
headers.set("User-Agent", req.headers.get("user-agent") ?? "");
if (ip) {
headers.set("mxl-client-ip", ip);
}
return headers;
}
async function handleApiRoute(req, apiUrl, apiPath) {
const headers = getClientHeaders(req);
try {
const res = await fetch(`${apiUrl}${apiPath}`, {
method: req.method,
headers,
body: req.method === "POST" ? JSON.stringify(await req.json()) : void 0
});
if (res.headers.get("content-type")?.includes("application/json")) {
return import_server.NextResponse.json(await res.json(), { status: res.status });
}
return import_server.NextResponse.json(await res.text(), { status: res.status });
} catch (e) {
return import_server.NextResponse.json(
{
error: "Failed to proxy request",
message: e instanceof Error ? e.message : String(e)
},
{ status: 500 }
);
}
}
async function handleScriptProxyRoute(req) {
const url = new URL(req.url);
const pathname = url.pathname;
if (!pathname.endsWith(SCRIPT_PATH)) {
return import_server.NextResponse.json({ error: "Not found" }, { status: 404 });
}
let scriptUrl = `${SCRIPT_URL}${SCRIPT_PATH}`;
if (url.searchParams.size > 0) {
scriptUrl += `?${url.searchParams.toString()}`;
}
try {
const res = await fetch(scriptUrl, {
// @ts-expect-error
next: { revalidate: 86400 }
});
const text = await res.text();
const etag = `"${(0, import_node_crypto.createHash)("md5").update(scriptUrl + text).digest("hex")}"`;
return new import_server.NextResponse(text, {
headers: {
"Content-Type": "text/javascript",
"Cache-Control": "public, max-age=86400, stale-while-revalidate=86400",
ETag: etag
}
});
} catch (e) {
return import_server.NextResponse.json(
{
error: "Failed to fetch script",
message: e instanceof Error ? e.message : String(e)
},
{ status: 500 }
);
}
}
function createRouteHandler(options) {
const apiUrl = options?.apiUrl ?? DEFAULT_API_URL;
const handler = async function handler2(req) {
const url = new URL(req.url);
const pathname = url.pathname;
const method = req.method;
if (method === "GET" && pathname.endsWith(SCRIPT_PATH)) {
return handleScriptProxyRoute(req);
}
const apiPathMatch = pathname.indexOf("/track");
if (apiPathMatch === -1) {
return import_server.NextResponse.json({ error: "Not found" }, { status: 404 });
}
const apiPath = pathname.substring(apiPathMatch);
return handleApiRoute(req, apiUrl, apiPath);
};
handler.GET = handler;
handler.POST = handler;
return handler;
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
createRouteHandler
});