Zalvena/packages/react/src/index.tsx
2023-12-29 09:38:24 -03:00

83 lines
2 KiB
TypeScript

'use client';
import { createContext, useContext, useEffect } from 'react';
import { getApiUrl, inMemorySessionId, sendEvent, validateAppKey, type AptabaseOptions } from '../../shared';
// Session expires after 1 hour of inactivity
const SESSION_TIMEOUT = 1 * 60 * 60;
const sdkVersion = `aptabase-react@${process.env.PKG_VERSION}`;
let _appKey = '';
let _apiUrl: string | undefined;
let _options: AptabaseOptions | undefined;
type ContextProps = {
appKey?: string;
options?: AptabaseOptions;
};
function init(appKey: string, options?: AptabaseOptions) {
if (!validateAppKey(appKey)) return;
_apiUrl = options?.apiUrl ?? getApiUrl(appKey, options);
_appKey = appKey;
_options = options;
}
async function trackEvent(eventName: string, props?: Record<string, string | number | boolean>): Promise<void> {
if (!_apiUrl) return;
const sessionId = inMemorySessionId(SESSION_TIMEOUT);
await sendEvent({
apiUrl: _apiUrl,
sessionId,
appKey: _appKey,
isDebug: _options?.isDebug,
appVersion: _options?.appVersion,
sdkVersion,
eventName,
props,
});
}
const AptabaseContext = createContext<ContextProps>({});
type Props = {
appKey: string;
options?: AptabaseOptions;
children: React.ReactNode;
};
export { type AptabaseOptions };
export type AptabaseClient = {
trackEvent: typeof trackEvent;
};
export function AptabaseProvider({ appKey, options, children }: Props) {
useEffect(() => {
init(appKey, options);
}, [appKey, options]);
return <AptabaseContext.Provider value={{ appKey, options }}>{children}</AptabaseContext.Provider>;
}
export function useAptabase(): AptabaseClient {
const ctx = useContext(AptabaseContext);
if (!ctx.appKey) {
return {
trackEvent: () => {
console.warn(
`Aptabase: useAptabase must be used within AptabaseProvider. Did you forget to wrap your app in <AptabaseProvider>?`,
);
return Promise.resolve();
},
};
}
return {
trackEvent,
};
}