sdk: add express sdk
This commit is contained in:
@@ -52,6 +52,8 @@ function createContextLogger(request: FastifyRequest) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const GLOBAL_PROPERTIES = ['__path', '__referrer'];
|
||||||
|
|
||||||
export async function postEvent(
|
export async function postEvent(
|
||||||
request: FastifyRequest<{
|
request: FastifyRequest<{
|
||||||
Body: PostEventPayload;
|
Body: PostEventPayload;
|
||||||
@@ -84,7 +86,7 @@ export async function postEvent(
|
|||||||
const origin = request.headers.origin!;
|
const origin = request.headers.origin!;
|
||||||
const ua = request.headers['user-agent']!;
|
const ua = request.headers['user-agent']!;
|
||||||
const uaInfo = parseUserAgent(ua);
|
const uaInfo = parseUserAgent(ua);
|
||||||
const salts = await getSalts();
|
const [geo, salts] = await Promise.all([parseIp(ip), getSalts()]);
|
||||||
const currentDeviceId = generateDeviceId({
|
const currentDeviceId = generateDeviceId({
|
||||||
salt: salts.current,
|
salt: salts.current,
|
||||||
origin,
|
origin,
|
||||||
@@ -114,18 +116,11 @@ export async function postEvent(
|
|||||||
sessionId: event?.sessionId || '',
|
sessionId: event?.sessionId || '',
|
||||||
profileId,
|
profileId,
|
||||||
projectId,
|
projectId,
|
||||||
properties: Object.assign(
|
properties: Object.assign({}, omit(GLOBAL_PROPERTIES, properties)),
|
||||||
{},
|
|
||||||
omit(['__path', '__referrer'], properties),
|
|
||||||
{
|
|
||||||
hash,
|
|
||||||
query,
|
|
||||||
}
|
|
||||||
),
|
|
||||||
createdAt,
|
createdAt,
|
||||||
country: event?.country ?? '',
|
country: event?.country || geo.country || '',
|
||||||
city: event?.city ?? '',
|
city: event?.city || geo.city || '',
|
||||||
region: event?.region ?? '',
|
region: event?.region || geo.region || '',
|
||||||
continent: event?.continent ?? '',
|
continent: event?.continent ?? '',
|
||||||
os: event?.os ?? '',
|
os: event?.os ?? '',
|
||||||
osVersion: event?.osVersion ?? '',
|
osVersion: event?.osVersion ?? '',
|
||||||
@@ -164,11 +159,10 @@ export async function postEvent(
|
|||||||
return reply.status(200).send('');
|
return reply.status(200).send('');
|
||||||
}
|
}
|
||||||
|
|
||||||
const [geo, sessionEndJobCurrentDeviceId, sessionEndJobPreviousDeviceId] =
|
const [sessionEndJobCurrentDeviceId, sessionEndJobPreviousDeviceId] =
|
||||||
await withTiming(
|
await withTiming(
|
||||||
'Get geo and jobs from queue',
|
'Get geo and jobs from queue',
|
||||||
Promise.all([
|
Promise.all([
|
||||||
parseIp(ip),
|
|
||||||
findJobByPrefix(
|
findJobByPrefix(
|
||||||
eventsQueue,
|
eventsQueue,
|
||||||
`sessionEnd:${projectId}:${currentDeviceId}:`
|
`sessionEnd:${projectId}:${currentDeviceId}:`
|
||||||
@@ -225,9 +219,9 @@ export async function postEvent(
|
|||||||
profileId,
|
profileId,
|
||||||
projectId,
|
projectId,
|
||||||
sessionId: createSessionStart ? uuid() : sessionStartEvent?.sessionId ?? '',
|
sessionId: createSessionStart ? uuid() : sessionStartEvent?.sessionId ?? '',
|
||||||
properties: Object.assign({}, omit(['__path', '__referrer'], properties), {
|
properties: Object.assign({}, omit(GLOBAL_PROPERTIES, properties), {
|
||||||
hash,
|
__hash: hash,
|
||||||
query,
|
__query: query,
|
||||||
}),
|
}),
|
||||||
createdAt,
|
createdAt,
|
||||||
country: geo.country,
|
country: geo.country,
|
||||||
|
|||||||
50
packages/sdks/express/index.ts
Normal file
50
packages/sdks/express/index.ts
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
import type { NextFunction, Request, Response } from 'express';
|
||||||
|
import { getClientIp } from 'request-ip';
|
||||||
|
|
||||||
|
import type { OpenpanelSdkOptions } from '@openpanel/sdk';
|
||||||
|
import { OpenpanelSdk } from '@openpanel/sdk';
|
||||||
|
|
||||||
|
export * from '@openpanel/sdk';
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-namespace
|
||||||
|
namespace Express {
|
||||||
|
export interface Request {
|
||||||
|
op: OpenpanelSdk;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export type OpenpanelOptions = OpenpanelSdkOptions & {
|
||||||
|
trackRequest?: (url: string) => boolean;
|
||||||
|
getProfileId?: (req: Request) => string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function createMiddleware(options: OpenpanelOptions) {
|
||||||
|
return function middleware(req: Request, res: Response, next: NextFunction) {
|
||||||
|
const sdk = new OpenpanelSdk(options);
|
||||||
|
const ip = getClientIp(req);
|
||||||
|
if (ip) {
|
||||||
|
sdk.api.headers['x-forwarded-for'] = ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.getProfileId) {
|
||||||
|
const profileId = options.getProfileId(req);
|
||||||
|
if (profileId) {
|
||||||
|
sdk.setProfileId(profileId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.trackRequest?.(req.url)) {
|
||||||
|
sdk.event('request', {
|
||||||
|
url: req.url,
|
||||||
|
method: req.method,
|
||||||
|
query: req.query,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
req.op = sdk;
|
||||||
|
|
||||||
|
return next();
|
||||||
|
};
|
||||||
|
}
|
||||||
36
packages/sdks/express/package.json
Normal file
36
packages/sdks/express/package.json
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
{
|
||||||
|
"name": "@openpanel/express",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"module": "index.ts",
|
||||||
|
"scripts": {
|
||||||
|
"build": "rm -rf dist && tsup",
|
||||||
|
"lint": "eslint .",
|
||||||
|
"format": "prettier --check \"**/*.{mjs,ts,md,json}\"",
|
||||||
|
"typecheck": "tsc --noEmit"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@openpanel/sdk": "workspace:*",
|
||||||
|
"request-ip": "^3.3.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"express": "^3.0.0 || ^4.0.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@openpanel/eslint-config": "workspace:*",
|
||||||
|
"@openpanel/prettier-config": "workspace:*",
|
||||||
|
"@openpanel/tsconfig": "workspace:*",
|
||||||
|
"@types/express": "^4.17.21",
|
||||||
|
"@types/request-ip": "^0.0.41",
|
||||||
|
"eslint": "^8.48.0",
|
||||||
|
"prettier": "^3.0.3",
|
||||||
|
"tsup": "^7.2.0",
|
||||||
|
"typescript": "^5.2.2"
|
||||||
|
},
|
||||||
|
"eslintConfig": {
|
||||||
|
"root": true,
|
||||||
|
"extends": [
|
||||||
|
"@openpanel/eslint-config/base"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"prettier": "@openpanel/prettier-config"
|
||||||
|
}
|
||||||
8
packages/sdks/express/tsconfig.json
Normal file
8
packages/sdks/express/tsconfig.json
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"extends": "@openpanel/tsconfig/base.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"incremental": false,
|
||||||
|
"outDir": "dist"
|
||||||
|
},
|
||||||
|
"exclude": ["dist"]
|
||||||
|
}
|
||||||
9
packages/sdks/express/tsup.config.ts
Normal file
9
packages/sdks/express/tsup.config.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import { defineConfig } from 'tsup';
|
||||||
|
|
||||||
|
import config from '@openpanel/tsconfig/tsup.config.json' assert { type: 'json' };
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
...(config as any),
|
||||||
|
entry: ['index.ts', 'cdn.ts'],
|
||||||
|
format: ['cjs', 'esm', 'iife'],
|
||||||
|
});
|
||||||
40
pnpm-lock.yaml
generated
40
pnpm-lock.yaml
generated
@@ -891,6 +891,46 @@ importers:
|
|||||||
specifier: ^5.2.2
|
specifier: ^5.2.2
|
||||||
version: 5.3.3
|
version: 5.3.3
|
||||||
|
|
||||||
|
packages/sdks/express:
|
||||||
|
dependencies:
|
||||||
|
'@openpanel/sdk':
|
||||||
|
specifier: workspace:*
|
||||||
|
version: link:../sdk
|
||||||
|
express:
|
||||||
|
specifier: ^3.0.0 || ^4.0.0
|
||||||
|
version: 4.18.2
|
||||||
|
request-ip:
|
||||||
|
specifier: ^3.3.0
|
||||||
|
version: 3.3.0
|
||||||
|
devDependencies:
|
||||||
|
'@openpanel/eslint-config':
|
||||||
|
specifier: workspace:*
|
||||||
|
version: link:../../../tooling/eslint
|
||||||
|
'@openpanel/prettier-config':
|
||||||
|
specifier: workspace:*
|
||||||
|
version: link:../../../tooling/prettier
|
||||||
|
'@openpanel/tsconfig':
|
||||||
|
specifier: workspace:*
|
||||||
|
version: link:../../../tooling/typescript
|
||||||
|
'@types/express':
|
||||||
|
specifier: ^4.17.21
|
||||||
|
version: 4.17.21
|
||||||
|
'@types/request-ip':
|
||||||
|
specifier: ^0.0.41
|
||||||
|
version: 0.0.41
|
||||||
|
eslint:
|
||||||
|
specifier: ^8.48.0
|
||||||
|
version: 8.56.0
|
||||||
|
prettier:
|
||||||
|
specifier: ^3.0.3
|
||||||
|
version: 3.2.5
|
||||||
|
tsup:
|
||||||
|
specifier: ^7.2.0
|
||||||
|
version: 7.3.0(typescript@5.3.3)
|
||||||
|
typescript:
|
||||||
|
specifier: ^5.2.2
|
||||||
|
version: 5.3.3
|
||||||
|
|
||||||
packages/sdks/nextjs:
|
packages/sdks/nextjs:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@openpanel/web':
|
'@openpanel/web':
|
||||||
|
|||||||
Reference in New Issue
Block a user