import { City } from '@maxmind/geoip2-node'; import { Response, Headers } from 'node-fetch'; /** Input for a PostHog plugin. */ export type PluginInput = { config?: Record; attachments?: Record; global?: Record; /** @deprecated */ jobs?: Record; /** @deprecated */ metrics?: Record; }; export interface Webhook { url: string; body: string; headers?: Record; method?: 'POST' | 'GET' | 'PUT' | 'DELETE' | 'PATCH'; } /** A PostHog plugin. */ export interface Plugin { /** Ran when the plugin is loaded by the PostHog plugin server. */ setupPlugin?: (meta: Meta) => void; /** Ran when the plugin is unloaded by the PostHog plugin server. */ teardownPlugin?: (meta: Meta) => void; /** @deprecated */ getSettings?: (meta: Meta) => PluginSettings; /** Not supported yet: Used for filtering events, return True to keep the event and False to drop it. */ filterEvent?: (event: PostHogEvent, meta: Meta) => boolean; /** Not supported yet: Used for modifying events, return the updated event */ modifyEvent?: (event: PostHogEvent, meta: Meta) => PostHogEvent; /** For filtering or modifing events */ processEvent?: (event: PluginEvent, meta: Meta) => PluginEvent | null | Promise; /** @deprecated: use processEvent */ processEventBatch?: (eventBatch: PluginEvent[], meta: Meta) => PluginEvent[] | Promise; /** @deprecated: use composeWebhook */ exportEvents?: (events: ProcessedPluginEvent[], meta: Meta) => void | Promise; /** @deprecated: use composeWebhook */ onEvent?: (event: ProcessedPluginEvent, meta: Meta) => void | Promise; onEventWithPostHogEvent?: (event: PostHogEvent, meta: Meta) => Promise | void; /** Used for exporting a single event */ composeWebhook?: (event: PostHogEvent, meta: Meta) => Webhook | null; /** @deprecated: */ runEveryMinute?: (meta: Meta) => void; /** @deprecated: */ runEveryHour?: (meta: Meta) => void; /** @deprecated: */ runEveryDay?: (meta: Meta) => void; /** @deprecated */ jobs?: { [K in keyof Meta['jobs']]: (opts: Parameters['jobs'][K]>[0], meta: Meta) => void | Promise; }; /** @deprecated */ metrics?: { [K in keyof Meta['metrics']]: AllowedMetricsOperations; }; __internalMeta?: Meta; } export type PluginMeta = T extends { __internalMeta?: infer M; } ? M : never; export type Properties = Record; /** We're moving to a single PostHogEvent model use this in any future apps/plugins */ export interface PostHogEvent { /** The assigned UUIDT of the event. */ uuid: string; team_id: number; distinct_id: string; event: string; timestamp: Date; /** Optionally contains * $ip - for ip address, which will be removed later if project settings anonymize_ips is true * $set - for person properties to set * $set_once - for person properties to set if not already set * $elements_chain - for autocapture elements chain */ properties: Properties; person?: PostHogPerson; groups?: Record; } export interface PostHogPerson { uuid: string; properties: Properties; posthog_url: string; } export interface PostHogGroup { key: string; properties: Properties; posthog_url: string; } export interface PluginAttachment { content_type: string; file_name: string; contents: any; } interface BasePluginMeta { cache: CacheExtension; storage: StorageExtension; geoip: GeoIPExtension; config: Record; global: Record; attachments: Record; jobs: Record JobControls>; metrics: Record>; utils: UtilsExtension; } export interface Meta extends BasePluginMeta { attachments: Input['attachments'] extends Record ? Input['attachments'] : Record; config: Input['config'] extends Record ? Input['config'] : Record; global: Input['global'] extends Record ? Input['global'] : Record; jobs: Input['jobs'] extends Record ? MetaJobsFromJobOptions : Record JobControls>; metrics: Input['metrics'] extends Record ? MetaMetricsFromMetricsOptions : Record; } type ConfigDependencyArrayValue = string | undefined; type ConfigDependencySubArray = ConfigDependencyArrayValue[]; type ConfigDependencyArray = ConfigDependencySubArray[]; export interface PluginConfigStructure { key?: string; name?: string; default?: string; hint?: string; markdown?: string; order?: number; required?: boolean; secret?: boolean; required_if?: ConfigDependencyArray; visible_if?: ConfigDependencyArray; } export interface PluginConfigDefault extends PluginConfigStructure { type?: 'string' | 'json' | 'attachment'; } export interface PluginConfigChoice extends PluginConfigStructure { type: 'choice'; choices: string[]; } export type PluginConfigSchema = PluginConfigDefault | PluginConfigChoice; export interface ConsoleExtension { log: (...args: unknown[]) => void; error: (...args: unknown[]) => void; debug: (...args: unknown[]) => void; info: (...args: unknown[]) => void; warn: (...args: unknown[]) => void; } export interface PluginPerson { uuid: string; team_id: number; properties: Properties; created_at: string; } export declare enum MetricsOperation { Sum = "sum", Min = "min", Max = "max" } export type AllowedMetricsOperations = MetricsOperation.Sum | MetricsOperation.Max | MetricsOperation.Min; export type PluginSettings = { /** Experimental: Some plugins incur high costs for small batches, e.g. S3. In these cases we want to signal that the plugin would prefer larger batches. There are other plugins that may not be written to handle large batches, for these we will want to keep batches small to not break their behaviour. Defaults to `false`. */ handlesLargeBatches?: boolean; }; /** @deprecated: Use PostHogEvent.properties['$elements_chain'] */ export interface Element { text?: string; tag_name?: string; href?: string; attr_id?: string; attr_class?: string[]; nth_child?: number; nth_of_type?: number; attributes?: Record; event_id?: number; order?: number; group_id?: number; } /** @deprecated: Use PostHogEvent */ export interface PluginEvent { distinct_id: string; ip: string | null; site_url: string; team_id: number; now: string; event: string; sent_at?: string; properties?: Properties; timestamp?: string; offset?: number; /** Person properties update (override). */ $set?: Properties; /** Person properties update (if not set). */ $set_once?: Properties; /** The assigned UUIDT of the event. */ uuid: string; /** Person associated with the original distinct ID of the event. */ person?: PluginPerson; } /** @deprecated: Use PostHogEvent */ export interface ProcessedPluginEvent { distinct_id: string; ip: string | null; team_id: number; event: string; properties: Properties; timestamp: string; /** Person properties update (override). */ $set?: Properties; /** Person properties update (if not set). */ $set_once?: Properties; /** The assigned UUIDT of the event. */ uuid: string; /** Person associated with the original distinct ID of the event. */ person?: PluginPerson; /** We process `$elements` out of `properties`, so we want to make sure we * maintain this in the processed event that we pass to plugins */ elements?: Element[]; } type JobOptions = Record | undefined; type JobControls = { runNow: () => Promise; runIn: (duration: number, unit: string) => Promise; runAt: (date: Date) => Promise; }; interface MetricsControlsIncrement { increment: (value: number) => Promise; } interface MetricsControlsMax { max: (value: number) => Promise; } interface MetricsControlsMin { min: (value: number) => Promise; } type FullMetricsControls = MetricsControlsIncrement & MetricsControlsMax & MetricsControlsMin; type MetricsControls = V extends MetricsOperation.Sum ? MetricsControlsIncrement : V extends MetricsOperation.Max ? MetricsControlsMax : MetricsControlsMin; type MetaMetricsFromMetricsOptions> = { [K in keyof J]: MetricsControls; }; type MetaJobsFromJobOptions> = { [K in keyof J]: (opts: J[K]) => JobControls; }; export interface CacheOptions { /** Whether input should be JSON-stringified/parsed. */ jsonSerialize?: boolean; } export interface CacheExtension { set: (key: string, value: unknown, ttlSeconds?: number, options?: CacheOptions) => Promise; get: (key: string, defaultValue: unknown, options?: CacheOptions) => Promise; incr: (key: string) => Promise; expire: (key: string, ttlSeconds: number) => Promise; lpush: (key: string, elementOrArray: unknown[]) => Promise; lrange: (key: string, startIndex: number, endIndex: number) => Promise; llen: (key: string) => Promise; lpop: (key: string, count: number) => Promise; lrem: (key: string, count: number, elementKey: string) => Promise; } export interface StorageExtension { set: (key: string, value: unknown) => Promise; get: (key: string, defaultValue: unknown) => Promise; del: (key: string) => Promise; } export interface GeoIPExtension { locate: (ip: string) => Promise; } export interface UtilsExtension { cursor: CursorUtils; } export interface CursorUtils { init: (key: string, initialValue?: number) => Promise; increment: (key: string, incrementBy?: number) => Promise; } interface ApiMethodOptions { headers?: Headers; data?: Record; host?: string; projectApiKey?: string; personalApiKey?: string; } export interface ApiExtension { get(path: string, options?: ApiMethodOptions): Promise; post(path: string, options?: ApiMethodOptions): Promise; put(path: string, options?: ApiMethodOptions): Promise; delete(path: string, options?: ApiMethodOptions): Promise; } export interface PostHogExtension { capture(event: string, properties?: Record): Promise; api: ApiExtension; } export {};