You're Invited:Meet the Socket Team at RSAC and BSidesSF 2026, March 23–26.RSVP
Socket
Book a DemoSign in
Socket

@openpanel/express

Package Overview
Dependencies
Maintainers
1
Versions
11
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@openpanel/express - npm Package Compare versions

Comparing version
1.0.4
to
1.0.5
+85
README.md
# Express
The Express middleware is a basic wrapper around Javascript SDK. It provides a simple way to add the SDK to your Express application.
> 📖 **Full documentation:** [https://openpanel.dev/docs/sdks/express](https://openpanel.dev/docs/sdks/express)
---
Looking for a step-by-step tutorial? Check out the [Express analytics guide](https://openpanel.dev/guides/express-analytics).
## Installation
```bash
pnpm install @openpanel/express
```
## Usage
The default export of `@openpanel/express` is a function that returns an Express middleware. It will also append the Openpanel SDK to the `req` object.
You can access it via `req.op`.
```ts
import express from 'express';
import createOpenpanelMiddleware from '@openpanel/express';
const app = express();
app.use(
createOpenpanelMiddleware({
clientId: 'xxx',
clientSecret: 'xxx',
// trackRequest(url) {
// return url.includes('/v1')
// },
// getProfileId(req) {
// return req.user.id
// }
})
);
app.get('/sign-up', (req, res) => {
// track sign up events
req.op.track('sign-up', {
email: req.body.email,
});
res.send('Hello World');
});
app.listen(3000, () => {
console.log('Server is running on http://localhost:3000');
});
```
### Options
##### Common options
- `apiUrl` - The url of the openpanel API or your self-hosted instance
- `clientId` - The client id of your application
- `clientSecret` - The client secret of your application (**only required for server-side events**)
- `filter` - A function that will be called before sending an event. If it returns false, the event will not be sent
- `disabled` - If true, the library will not send any events
#### Express options
- `trackRequest` - A function that returns `true` if the request should be tracked.
- `getProfileId` - A function that returns the profile ID of the user making the request.
## Typescript
If `req.op` is not typed you can extend the `Request` interface.
```ts
import { OpenPanel } from '@openpanel/express';
declare global {
namespace Express {
export interface Request {
op: OpenPanel;
}
}
}
```
+1
-1

@@ -1,1 +0,1 @@

"use strict";(()=>{var f=["openpanel-client-ip","cf-connecting-ip","true-client-ip","x-client-ip","x-forwarded-for","x-real-ip","fastly-client-ip","x-cluster-client-ip","x-appengine-user-ip","do-connecting-ip","x-nf-client-connection-ip","x-forwarded","forwarded"];function l(e){if(e.startsWith("::ffff:")){let t=e.substring(7);return l(t)}if(e==="::1"||e.startsWith("fc00:")||e.startsWith("fd00:")||e.startsWith("fe80:")||e.startsWith("127.")||e.startsWith("10."))return!1;if(e.startsWith("172.")){let t=e.split(".");if(t.length>=2){let r=Number.parseInt(t[1]||"0",10);if(r>=16&&r<=31)return!1}}return!(e.startsWith("192.168.")||e.startsWith("169.254."))}function u(){return typeof process<"u"&&process.env?.IP_HEADER_ORDER?process.env.IP_HEADER_ORDER.split(",").map(e=>e.trim()):f}function o(e){let t=/^(\d{1,3}\.){3}\d{1,3}$/,r=/^([0-9a-fA-F]{0,4}:){2,7}[0-9a-fA-F]{0,4}$/;return l(e)&&(t.test(e)||r.test(e))}function d(e,t){let r=u();t&&(r=[t]);for(let n of r){let s=null;if(e instanceof Headers)s=e.get(n);else{let i=e[n];Array.isArray(i)?s=i[0]||null:s=i||null}if(s){if(n==="x-forwarded-for"){let i=s.split(",")[0]?.trim();if(i&&o(i))return{ip:i,header:n}}else if(n==="forwarded"){let a=s.match(/for=(?:"?\[?([^\]"]+)\]?"?)/i)?.[1];if(a&&o(a))return{ip:a,header:n}}else if(o(s))return{ip:s,header:n}}}return{ip:"",header:""}}var h=class{constructor(e){this.baseUrl=e.baseUrl,this.headers={"Content-Type":"application/json",...e.defaultHeaders},this.maxRetries=e.maxRetries??3,this.initialRetryDelay=e.initialRetryDelay??500}async resolveHeaders(){let e={};for(let[t,r]of Object.entries(this.headers)){let n=await r;n!==null&&(e[t]=n)}return e}addHeader(e,t){this.headers[e]=t}async post(e,t,r,n){try{let s=await fetch(e,{method:"POST",headers:await this.resolveHeaders(),body:t?JSON.stringify(t??{}):void 0,keepalive:!0,...r});if(s.status===401)return null;if(s.status!==200&&s.status!==202)throw new Error(`HTTP error! status: ${s.status}`);let i=await s.text();return i?JSON.parse(i):null}catch(s){if(n<this.maxRetries){let i=this.initialRetryDelay*2**n;return await new Promise(a=>setTimeout(a,i)),this.post(e,t,r,n+1)}return console.error("Max retries reached:",s),null}}async fetch(e,t,r={}){let n=`${this.baseUrl}${e}`;return this.post(n,t,r,0)}},p=class{constructor(e){this.options=e,this.queue=[];let t={"openpanel-client-id":e.clientId};e.clientSecret&&(t["openpanel-client-secret"]=e.clientSecret),t["openpanel-sdk-name"]=e.sdk||"node",t["openpanel-sdk-version"]=e.sdkVersion||"1.0.3",this.api=new h({baseUrl:e.apiUrl||"https://api.openpanel.dev",defaultHeaders:t})}init(){}ready(){this.options.waitForProfile=!1,this.flush()}async send(e){return this.options.disabled||this.options.filter&&!this.options.filter(e)?Promise.resolve():this.options.waitForProfile&&!this.profileId?(this.queue.push(e),Promise.resolve()):this.api.fetch("/track",e)}setGlobalProperties(e){this.global={...this.global,...e}}async track(e,t){return this.log("track event",e,t),this.send({type:"track",payload:{name:e,profileId:t?.profileId??this.profileId,properties:{...this.global??{},...t??{}}}})}async identify(e){if(this.log("identify user",e),e.profileId&&(this.profileId=e.profileId,this.flush()),Object.keys(e).length>1)return this.send({type:"identify",payload:{...e,properties:{...this.global,...e.properties}}})}async alias(e){}async increment(e){return this.send({type:"increment",payload:e})}async decrement(e){return this.send({type:"decrement",payload:e})}async revenue(e,t){let r=t?.deviceId;return delete t?.deviceId,this.track("revenue",{...t??{},...r?{__deviceId:r}:{},__revenue:e})}async fetchDeviceId(){return(await this.api.fetch("/track/device-id",void 0,{method:"GET",keepalive:!1}))?.deviceId??""}clear(){this.profileId=void 0}flush(){this.queue.forEach(e=>{this.send({...e,payload:{...e.payload,profileId:e.payload.profileId??this.profileId}})}),this.queue=[]}log(...e){this.options.debug&&console.log("[OpenPanel.dev]",...e)}};function y(e){return function(r,n,s){let i=new p(e),{ip:a}=d(r.headers);if(a&&i.api.addHeader("openpanel-client-ip",a),r.headers["user-agent"]&&i.api.addHeader("user-agent",r.headers["user-agent"]),e.trackRequest?.(r.url)){let c=e.getProfileId?e.getProfileId(r):void 0;i.track("request",{url:r.url,method:r.method,query:r.query,profileId:c})}return r.op=i,s()}}})();
"use strict";(()=>{var f=["openpanel-client-ip","cf-connecting-ip","true-client-ip","x-client-ip","x-forwarded-for","x-real-ip","fastly-client-ip","x-cluster-client-ip","x-appengine-user-ip","do-connecting-ip","x-nf-client-connection-ip","x-forwarded","forwarded"];function l(e){if(e.startsWith("::ffff:")){let t=e.substring(7);return l(t)}if(e==="::1"||e.startsWith("fc00:")||e.startsWith("fd00:")||e.startsWith("fe80:")||e.startsWith("127.")||e.startsWith("10."))return!1;if(e.startsWith("172.")){let t=e.split(".");if(t.length>=2){let r=Number.parseInt(t[1]||"0",10);if(r>=16&&r<=31)return!1}}return!(e.startsWith("192.168.")||e.startsWith("169.254."))}function u(){return typeof process<"u"&&process.env?.IP_HEADER_ORDER?process.env.IP_HEADER_ORDER.split(",").map(e=>e.trim()):f}function o(e){let t=/^(\d{1,3}\.){3}\d{1,3}$/,r=/^([0-9a-fA-F]{0,4}:){2,7}[0-9a-fA-F]{0,4}$/;return l(e)&&(t.test(e)||r.test(e))}function d(e,t){let r=u();t&&(r=[t]);for(let n of r){let s=null;if(e instanceof Headers)s=e.get(n);else{let i=e[n];Array.isArray(i)?s=i[0]||null:s=i||null}if(s){if(n==="x-forwarded-for"){let i=s.split(",")[0]?.trim();if(i&&o(i))return{ip:i,header:n}}else if(n==="forwarded"){let a=s.match(/for=(?:"?\[?([^\]"]+)\]?"?)/i)?.[1];if(a&&o(a))return{ip:a,header:n}}else if(o(s))return{ip:s,header:n}}}return{ip:"",header:""}}var h=class{constructor(e){this.baseUrl=e.baseUrl,this.headers={"Content-Type":"application/json",...e.defaultHeaders},this.maxRetries=e.maxRetries??3,this.initialRetryDelay=e.initialRetryDelay??500}async resolveHeaders(){let e={};for(let[t,r]of Object.entries(this.headers)){let n=await r;n!==null&&(e[t]=n)}return e}addHeader(e,t){this.headers[e]=t}async post(e,t,r,n){try{let s=await fetch(e,{method:"POST",headers:await this.resolveHeaders(),body:t?JSON.stringify(t??{}):void 0,keepalive:!0,...r});if(s.status===401)return null;if(s.status!==200&&s.status!==202)throw new Error(`HTTP error! status: ${s.status}`);let i=await s.text();return i?JSON.parse(i):null}catch(s){if(n<this.maxRetries){let i=this.initialRetryDelay*2**n;return await new Promise(a=>setTimeout(a,i)),this.post(e,t,r,n+1)}return console.error("Max retries reached:",s),null}}async fetch(e,t,r={}){let n=`${this.baseUrl}${e}`;return this.post(n,t,r,0)}},p=class{constructor(e){this.options=e,this.queue=[];let t={"openpanel-client-id":e.clientId};e.clientSecret&&(t["openpanel-client-secret"]=e.clientSecret),t["openpanel-sdk-name"]=e.sdk||"node",t["openpanel-sdk-version"]=e.sdkVersion||"1.0.4",this.api=new h({baseUrl:e.apiUrl||"https://api.openpanel.dev",defaultHeaders:t})}init(){}ready(){this.options.waitForProfile=!1,this.flush()}async send(e){return this.options.disabled||this.options.filter&&!this.options.filter(e)?Promise.resolve():this.options.waitForProfile&&!this.profileId?(this.queue.push(e),Promise.resolve()):this.api.fetch("/track",e)}setGlobalProperties(e){this.global={...this.global,...e}}async track(e,t){return this.log("track event",e,t),this.send({type:"track",payload:{name:e,profileId:t?.profileId??this.profileId,properties:{...this.global??{},...t??{}}}})}async identify(e){if(this.log("identify user",e),e.profileId&&(this.profileId=e.profileId,this.flush()),Object.keys(e).length>1)return this.send({type:"identify",payload:{...e,properties:{...this.global,...e.properties}}})}async alias(e){}async increment(e){return this.send({type:"increment",payload:e})}async decrement(e){return this.send({type:"decrement",payload:e})}async revenue(e,t){let r=t?.deviceId;return delete t?.deviceId,this.track("revenue",{...t??{},...r?{__deviceId:r}:{},__revenue:e})}async fetchDeviceId(){return(await this.api.fetch("/track/device-id",void 0,{method:"GET",keepalive:!1}))?.deviceId??""}clear(){this.profileId=void 0}flush(){this.queue.forEach(e=>{this.send({...e,payload:{...e.payload,profileId:e.payload.profileId??this.profileId}})}),this.queue=[]}log(...e){this.options.debug&&console.log("[OpenPanel.dev]",...e)}};function y(e){return function(r,n,s){let i=new p(e),{ip:a}=d(r.headers);if(a&&i.api.addHeader("openpanel-client-ip",a),r.headers["user-agent"]&&i.api.addHeader("user-agent",r.headers["user-agent"]),e.trackRequest?.(r.url)){let c=e.getProfileId?e.getProfileId(r):void 0;i.track("request",{url:r.url,method:r.method,query:r.query,profileId:c})}return r.op=i,s()}}})();
{
"name": "@openpanel/express",
"version": "1.0.4",
"version": "1.0.5",
"module": "./dist/index.js",
"config": {
"docPath": "apps/public/content/docs/(tracking)/sdks/express.mdx"
},
"scripts": {

@@ -10,3 +13,3 @@ "build": "rm -rf dist && tsup",

"dependencies": {
"@openpanel/sdk": "1.0.3",
"@openpanel/sdk": "1.0.4",
"@openpanel/common": "*"

@@ -28,3 +31,3 @@ },

"types": "./dist/index.d.ts",
"files": ["dist"],
"files": ["dist", "README.md"],
"exports": {

@@ -31,0 +34,0 @@ ".": {