working versions of nextjs and web

This commit is contained in:
goenning 2023-09-01 14:40:08 +01:00
parent 9c7e01e6d4
commit e104dd53dc
26 changed files with 267 additions and 425 deletions

View file

@ -3,15 +3,30 @@
"version": "0.1.0",
"type": "module",
"description": "Next.js SDK for Aptabase: Open Source, Privacy-First and Simple Analytics for Mobile, Desktop and Web Apps",
"types": "./dist/index.d.ts",
"sideEffects": false,
"exports": {
"./package.json": "./package.json",
".": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
"import": "./dist/index.js",
"require": "./dist/index.cjs",
"types": "./dist/index.d.ts"
},
"./client": {
"import": "./dist/client.js",
"require": "./dist/client.cjs",
"types": "./dist/client.d.ts"
},
"./server": {
"types": "./dist/server.d.ts",
"default": "./dist/server.js"
"import": "./dist/server.js",
"require": "./dist/server.cjs",
"types": "./dist/server.d.ts"
}
},
"typesVersions": {
"*": {
"*": [
"dist/*"
]
}
},
"repository": {
@ -25,7 +40,7 @@
"homepage": "https://github.com/aptabase/aptabase-js",
"license": "MIT",
"scripts": {
"build": "tsc"
"build": "tsup"
},
"files": [
"README.md",
@ -34,16 +49,9 @@
"package.json"
],
"dependencies": {
"@aptabase/node": "*",
"@aptabase/react": "*"
},
"devDependencies": {
"@rollup/plugin-replace": "5.0.2",
"@rollup/plugin-typescript": "11.1.3",
"rollup": "3.28.1",
"@rollup/plugin-terser": "0.4.3",
"tslib": "2.6.2",
"typescript": "5.2.2"
},
"peerDependencies": {
"react": "^18.0.0",
"next": "^13.0.0"

View file

@ -0,0 +1 @@
export * from '@aptabase/react';

View file

@ -1,5 +0,0 @@
type AptabaseState = {
appKey?: string;
};
declare var __APTABASE__: AptabaseState;

View file

@ -1,5 +1 @@
export * from '@aptabase/react';
export function init(appKey: string) {
globalThis.__APTABASE__ = { appKey };
}
export type README = 'Use @aptabase/next/server or @aptabase/next/client instead.';

View file

@ -1,62 +1,34 @@
import { trackEvent as nodeTrackEvent } from '@aptabase/node';
import { type NextIncomingMessage } from 'next/dist/server/request-meta';
import { headers } from 'next/headers';
export { init } from '@aptabase/node';
export async function trackEvent(
eventName: string,
props?: Record<string, string | number | boolean>,
req?: NextIncomingMessage,
): Promise<void> {
const appKey = globalThis.__APTABASE__.appKey;
if (!appKey) return Promise.resolve();
const headers = getHeaders(req);
if (!headers) return Promise.resolve();
const userAgent = getUserAgent(req);
if (!userAgent) return Promise.resolve();
const body = JSON.stringify({
timestamp: new Date().toISOString(),
sessionId: 'CHANGE-THIS',
eventName: eventName,
systemProps: {
isDebug: true,
locale: 'en',
appVersion: '',
sdkVersion: 'aptabase-nextjs@0.0.1',
},
props: props,
});
try {
const response = await fetch('http://localhost:3000/api/v0/event', {
method: 'POST',
headers: {
'User-Agent': userAgent,
'Content-Type': 'application/json',
'App-Key': appKey,
},
credentials: 'omit',
body,
});
if (response.status >= 300) {
const responseBody = await response.text();
console.warn(`Failed to send event "${eventName}": ${response.status} ${responseBody}`);
}
} catch (e) {
console.warn(`Failed to send event "${eventName}": ${e}`);
}
return nodeTrackEvent({ headers }, eventName, props);
}
function getUserAgent(req?: NextIncomingMessage): string | undefined {
function getHeaders(req?: NextIncomingMessage): Headers | undefined {
if (req) {
return req.headers['user-agent'] ?? 'Unknown';
// we only need the user-agent header
return new Headers({
'user-agent': req.headers['user-agent'] ?? '',
});
}
// headers() might throw an error if called outside of a request context.
try {
return headers().get('User-Agent') ?? 'Unknown';
return headers();
} catch {}
// If we're here, we're probably using the Pages Router and the user forgot to pass the req parameter.
// If we're here, the app is probably using the Pages Router and the developer forgot to pass the req parameter.
if (!req) {
console.warn("Aptabase: The 'req' parameter of trackEvent is required when using Pages Router.");
}

View file

@ -1,22 +1,14 @@
{
"compilerOptions": {
"declaration": true,
"esModuleInterop": true,
"lib": ["esnext", "dom"],
"module": "esnext",
"jsx": "react-jsx",
"moduleResolution": "node",
"noEmitOnError": true,
"noFallthroughCasesInSwitch": true,
"noImplicitReturns": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"outDir": "dist",
"sourceMap": true,
"target": "es6",
"strict": true,
"target": "es2020",
"types": ["node"],
},
"include": ["src/*", "src/global.d.ts"],
"exclude": ["node_modules"]
}
"moduleResolution": "node",
"esModuleInterop": true,
"baseUrl": ".",
"paths": {
"types": ["@types"]
},
"declaration": true,
"declarationDir": "./dist"
}
}

View file

@ -0,0 +1,11 @@
import { defineConfig } from 'tsup';
export default defineConfig({
entry: ['src/index.ts', 'src/server.ts', 'src/client.tsx'],
format: ['cjs', 'esm'],
dts: true,
splitting: false,
minify: true,
sourcemap: true,
clean: true,
});