This commit is contained in:
Carl-Gerhard Lindesvärd
2024-08-01 22:01:46 +02:00
committed by Carl-Gerhard Lindesvärd
parent 15e997129a
commit 2226cb463d
10 changed files with 73 additions and 83 deletions

View File

@@ -1,68 +1,21 @@
import { NextResponse } from 'next/server';
const VALID_PATHS = [
'/profile',
'/profile/increment',
'/profile/decrement',
'/event',
];
function getIp(req: Request) {
if (req.headers.get('X-Forwarded-For')) {
return req.headers.get('X-Forwarded-For')?.split(',')[0];
}
return req.headers.get('x-real-ip') ?? '0.0.0.0';
}
function getPath(params?: Record<string, unknown>) {
const segments = params?.op;
if (segments && Array.isArray(segments)) {
const path = `/${segments.join('/')}`;
if (VALID_PATHS.includes(path)) {
return path;
}
}
return null;
}
export function createNextRouteHandler({
clientId,
clientSecret,
url = 'https://api.openpanel.dev',
apiUrl = 'https://api.openpanel.dev',
}: {
clientId: string;
clientSecret: string;
url?: string;
apiUrl?: string;
}) {
return {
POST: async function POST(
req: Request,
{ params }: { params: Record<string, unknown> }
) {
const path = getPath(params);
if (!path) {
return NextResponse.json('Invalid path');
}
const headers = {
'user-agent': req.headers.get('user-agent')!,
'Content-Type': req.headers.get('Content-Type')!,
'openpanel-client-id': clientId,
'openpanel-client-secret': clientSecret,
'x-client-ip': getIp(req)!,
};
try {
const res = await fetch(`${url}${path}`, {
method: 'POST',
headers,
body: JSON.stringify(await req.json()),
});
return NextResponse.json(await res.text());
} catch (e) {
return NextResponse.json(e);
}
},
return async function POST(req: Request) {
const headers = new Headers(req.headers);
try {
const res = await fetch(`${apiUrl}/track`, {
method: 'POST',
headers,
body: JSON.stringify(await req.json()),
});
return NextResponse.json(await res.text());
} catch (e) {
return NextResponse.json(e);
}
};
}

View File

@@ -1,4 +1,6 @@
import React from 'react';
'use client';
import React, { useEffect } from 'react';
import Script from 'next/script';
import type {
@@ -11,13 +13,27 @@ import type {
} from '@openpanel/web';
export * from '@openpanel/web';
export { createNextRouteHandler } from './createNextRouteHandler';
const CDN_URL = 'https://openpanel.dev/op.js';
type OpenPanelComponentProps = OpenPanelOptions & {
type OpenPanelComponentProps = Omit<OpenPanelOptions, 'filter'> & {
profileId?: string;
cdnUrl?: string;
filter?: string;
};
const stringify = (obj: unknown) => {
if (typeof obj === 'object' && obj !== null && obj !== undefined) {
const entries = Object.entries(obj).map(([key, value]) => {
if (key === 'filter') {
return `"${key}":${value}`;
}
return `"${key}":${JSON.stringify(value)}`;
});
return `{${entries.join(',')}}`;
}
return JSON.stringify(obj);
};
export function OpenPanelComponent({
@@ -51,7 +67,7 @@ export function OpenPanelComponent({
__html: `window.op = window.op || function(...args) {(window.op.q = window.op.q || []).push(args)};
${methods
.map((method) => {
return `window.op('${method.name}', ${JSON.stringify(method.value)});`;
return `window.op('${method.name}', ${stringify(method.value)});`;
})
.join('\n')}`,
}}
@@ -67,7 +83,7 @@ export function IdentifyComponent(props: IdentifyComponentProps) {
<>
<Script
dangerouslySetInnerHTML={{
__html: `window.op('setProfile', ${JSON.stringify(props)});`,
__html: `window.op('identify', ${JSON.stringify(props)});`,
}}
/>
</>

View File

@@ -0,0 +1 @@
export { createNextRouteHandler } from './createNextRouteHandler';

View File

@@ -4,6 +4,6 @@ import config from '@openpanel/tsconfig/tsup.config.json' assert { type: 'json'
export default defineConfig({
...(config as any),
entry: ['index.tsx'],
entry: ['index.tsx', 'server.ts'],
external: ['react', 'next'],
});

View File

@@ -4,7 +4,6 @@
"module": "index.ts",
"scripts": {
"build": "rm -rf dist && tsup",
"build-for-openpanel": "pnpm build && cp dist/src/tracker.global.js ../../../apps/public/public/tracker.js",
"lint": "eslint .",
"format": "prettier --check \"**/*.{mjs,ts,md,json}\"",
"typecheck": "tsc --noEmit"