@mantajs/plugin-posthog-proxy 0.2.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/modules/posthog/api/[...path]/route.d.ts +6 -0
- package/dist/modules/posthog/api/[...path]/route.d.ts.map +1 -0
- package/dist/modules/posthog/api/[...path]/route.js +625 -0
- package/dist/modules/posthog/api/[...path]/route.js.map +1 -0
- package/dist/modules/posthog/commands/identify-user.d.ts +12 -0
- package/dist/modules/posthog/commands/identify-user.d.ts.map +1 -0
- package/dist/modules/posthog/commands/identify-user.js +31 -0
- package/dist/modules/posthog/commands/identify-user.js.map +1 -0
- package/dist/modules/posthog/commands/track-event.d.ts +15 -0
- package/dist/modules/posthog/commands/track-event.d.ts.map +1 -0
- package/dist/modules/posthog/commands/track-event.js +33 -0
- package/dist/modules/posthog/commands/track-event.js.map +1 -0
- package/dist/modules/posthog/entities/event/model.d.ts +3 -0
- package/dist/modules/posthog/entities/event/model.d.ts.map +1 -0
- package/dist/modules/posthog/entities/event/model.js +4 -0
- package/dist/modules/posthog/entities/event/model.js.map +1 -0
- package/dist/modules/posthog/entities/insight/model.d.ts +3 -0
- package/dist/modules/posthog/entities/insight/model.d.ts.map +1 -0
- package/dist/modules/posthog/entities/insight/model.js +4 -0
- package/dist/modules/posthog/entities/insight/model.js.map +1 -0
- package/dist/modules/posthog/entities/person/model.d.ts +3 -0
- package/dist/modules/posthog/entities/person/model.d.ts.map +1 -0
- package/dist/modules/posthog/entities/person/model.js +4 -0
- package/dist/modules/posthog/entities/person/model.js.map +1 -0
- package/dist/modules/posthog/queries/graph.d.ts +3 -0
- package/dist/modules/posthog/queries/graph.d.ts.map +1 -0
- package/dist/modules/posthog/queries/graph.js +23 -0
- package/dist/modules/posthog/queries/graph.js.map +1 -0
- package/dist/modules/posthog/queries/lib/execute.d.ts +26 -0
- package/dist/modules/posthog/queries/lib/execute.d.ts.map +1 -0
- package/dist/modules/posthog/queries/lib/execute.js +93 -0
- package/dist/modules/posthog/queries/lib/execute.js.map +1 -0
- package/dist/modules/posthog/queries/lib/schema.d.ts +13 -0
- package/dist/modules/posthog/queries/lib/schema.d.ts.map +1 -0
- package/dist/modules/posthog/queries/lib/schema.js +42 -0
- package/dist/modules/posthog/queries/lib/schema.js.map +1 -0
- package/dist/modules/posthog/queries/lib/translate.d.ts +15 -0
- package/dist/modules/posthog/queries/lib/translate.d.ts.map +1 -0
- package/dist/modules/posthog/queries/lib/translate.js +72 -0
- package/dist/modules/posthog/queries/lib/translate.js.map +1 -0
- package/dist/modules/posthog/schemas.d.ts +103 -0
- package/dist/modules/posthog/schemas.d.ts.map +1 -0
- package/dist/modules/posthog/schemas.js +42 -0
- package/dist/modules/posthog/schemas.js.map +1 -0
- package/package.json +37 -0
- package/src/index.ts +1 -0
- package/src/modules/posthog/api/[...path]/route.ts +672 -0
- package/src/modules/posthog/commands/identify-user.ts +32 -0
- package/src/modules/posthog/commands/track-event.ts +34 -0
- package/src/modules/posthog/entities/event/model.ts +4 -0
- package/src/modules/posthog/entities/insight/model.ts +4 -0
- package/src/modules/posthog/entities/person/model.ts +4 -0
- package/src/modules/posthog/queries/graph.ts +24 -0
- package/src/modules/posthog/queries/lib/execute.ts +111 -0
- package/src/modules/posthog/queries/lib/schema.ts +45 -0
- package/src/modules/posthog/queries/lib/translate.ts +73 -0
- package/src/modules/posthog/schemas.ts +48 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { defineCommand } from '@mantajs/core'
|
|
2
|
+
import { PostHog } from 'posthog-node'
|
|
3
|
+
import { postHogIdentifyInputSchema } from '../schemas'
|
|
4
|
+
|
|
5
|
+
export default defineCommand({
|
|
6
|
+
name: 'posthog:identify-user',
|
|
7
|
+
description:
|
|
8
|
+
'Identify an anonymous PostHog visitor with their properties. Links all past anonymous events to the known user.',
|
|
9
|
+
input: postHogIdentifyInputSchema,
|
|
10
|
+
async workflow(input, { step }) {
|
|
11
|
+
// step.action signature: (name, { invoke, compensate }) → returns a runner function
|
|
12
|
+
// that you must call with (input, ctx) to execute. Compensate is mandatory but a no-op
|
|
13
|
+
// here: identify writes are idempotent and there's no PostHog primitive to "un-identify".
|
|
14
|
+
return step.action('posthog-identify', {
|
|
15
|
+
invoke: async () => {
|
|
16
|
+
const token = process.env.POSTHOG_TOKEN
|
|
17
|
+
if (!token) return { success: false, error: 'POSTHOG_TOKEN env var not set' }
|
|
18
|
+
|
|
19
|
+
const posthog = new PostHog(token, { host: process.env.POSTHOG_HOST ?? 'https://eu.i.posthog.com' })
|
|
20
|
+
posthog.identify({
|
|
21
|
+
distinctId: input.distinctId,
|
|
22
|
+
properties: input.properties,
|
|
23
|
+
})
|
|
24
|
+
await posthog.shutdown()
|
|
25
|
+
return { success: true }
|
|
26
|
+
},
|
|
27
|
+
compensate: async () => {
|
|
28
|
+
// No-op — identify writes are idempotent.
|
|
29
|
+
},
|
|
30
|
+
})(input)
|
|
31
|
+
},
|
|
32
|
+
})
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { defineCommand } from '@mantajs/core'
|
|
2
|
+
import { PostHog } from 'posthog-node'
|
|
3
|
+
import { postHogCaptureInputSchema } from '../schemas'
|
|
4
|
+
|
|
5
|
+
export default defineCommand({
|
|
6
|
+
name: 'posthog:track-event',
|
|
7
|
+
description:
|
|
8
|
+
'Track a custom analytics event in PostHog (page view, click, purchase, sign-up, etc.). Use for sending server-side events.',
|
|
9
|
+
input: postHogCaptureInputSchema,
|
|
10
|
+
async workflow(input, { step }) {
|
|
11
|
+
// step.action signature: (name, { invoke, compensate }) → returns a runner function
|
|
12
|
+
// that you must call with (input, ctx) to execute. Compensate is mandatory but a no-op
|
|
13
|
+
// here: PostHog events are immutable once sent, so there's nothing to rollback if a
|
|
14
|
+
// later step in the workflow fails.
|
|
15
|
+
return step.action('posthog-capture', {
|
|
16
|
+
invoke: async () => {
|
|
17
|
+
const token = process.env.POSTHOG_TOKEN
|
|
18
|
+
if (!token) return { success: false, error: 'POSTHOG_TOKEN env var not set' }
|
|
19
|
+
|
|
20
|
+
const posthog = new PostHog(token, { host: process.env.POSTHOG_HOST ?? 'https://eu.i.posthog.com' })
|
|
21
|
+
posthog.capture({
|
|
22
|
+
event: input.event,
|
|
23
|
+
distinctId: input.distinctId,
|
|
24
|
+
properties: input.properties,
|
|
25
|
+
})
|
|
26
|
+
await posthog.shutdown()
|
|
27
|
+
return { success: true }
|
|
28
|
+
},
|
|
29
|
+
compensate: async () => {
|
|
30
|
+
// No-op — events are immutable.
|
|
31
|
+
},
|
|
32
|
+
})(input)
|
|
33
|
+
},
|
|
34
|
+
})
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// PostHog query graph extension — declares which entities this module owns and routes
|
|
2
|
+
// Manta query graph requests to PostHog's HogQL / Insights APIs.
|
|
3
|
+
//
|
|
4
|
+
// The file is auto-discovered by the framework (scans modules/{name}/queries/*.ts).
|
|
5
|
+
// Because its default export uses `extendQueryGraph`, the framework registers it on
|
|
6
|
+
// the QueryService as a resolver for the listed entities.
|
|
7
|
+
|
|
8
|
+
import { extendQueryGraph } from '@mantajs/core'
|
|
9
|
+
import { executeHogQL, executeInsights } from './lib/execute'
|
|
10
|
+
import { SUPPORTED_FILTERS } from './lib/schema'
|
|
11
|
+
|
|
12
|
+
export default extendQueryGraph({
|
|
13
|
+
owns: ['posthogEvent', 'posthogPerson', 'posthogInsight'],
|
|
14
|
+
supportedFilters: SUPPORTED_FILTERS,
|
|
15
|
+
async resolve(query) {
|
|
16
|
+
// Case-insensitive dispatch — caller may pass 'posthogInsight', 'PostHogInsight',
|
|
17
|
+
// 'posthoginsight', etc. depending on where they discovered the entity name (AI
|
|
18
|
+
// system prompt lowercases module names, for example).
|
|
19
|
+
if (typeof query.entity === 'string' && query.entity.toLowerCase() === 'posthoginsight') {
|
|
20
|
+
return executeInsights(query)
|
|
21
|
+
}
|
|
22
|
+
return executeHogQL(query)
|
|
23
|
+
},
|
|
24
|
+
})
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
// PostHog HogQL execution — runs SQL against the PostHog query endpoint and normalizes results.
|
|
2
|
+
|
|
3
|
+
import type { GraphQueryConfig } from '@mantajs/core'
|
|
4
|
+
import { MantaError } from '@mantajs/core'
|
|
5
|
+
import { DEFAULT_SORT, ENTITY_TO_TABLE } from './schema'
|
|
6
|
+
import { normalizeRow, translateFilters } from './translate'
|
|
7
|
+
|
|
8
|
+
export interface PostHogConnection {
|
|
9
|
+
host: string
|
|
10
|
+
personalApiKey: string
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Read PostHog connection info from environment variables. No plugin config — pure env.
|
|
15
|
+
* Throws MantaError if the personal API key is missing, so the caller (AI or HTTP) sees a clear message.
|
|
16
|
+
*/
|
|
17
|
+
export function readPostHogConnection(): PostHogConnection {
|
|
18
|
+
const host = process.env.POSTHOG_HOST ?? 'https://eu.i.posthog.com'
|
|
19
|
+
const personalApiKey = process.env.POSTHOG_API_KEY
|
|
20
|
+
if (!personalApiKey) {
|
|
21
|
+
throw new MantaError('INVALID_DATA', 'POSTHOG_API_KEY env var not set — cannot query PostHog data warehouse.')
|
|
22
|
+
}
|
|
23
|
+
return { host, personalApiKey }
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Resolve a query that targets posthogEvent or posthogPerson via HogQL.
|
|
28
|
+
*
|
|
29
|
+
* Entity name normalization: the extendQueryGraph() framework does a case-insensitive
|
|
30
|
+
* match when deciding which extension owns an entity, but passes the caller's original
|
|
31
|
+
* string to the resolver. Callers can therefore use 'posthogEvent', 'PostHogEvent', or
|
|
32
|
+
* 'posthogevent' (e.g. when the AI system prompt lowercases module names). We normalize
|
|
33
|
+
* against the canonical keys of ENTITY_TO_TABLE so every downstream lookup
|
|
34
|
+
* (translateFilters, normalizeRow) gets the canonical name.
|
|
35
|
+
*/
|
|
36
|
+
export async function executeHogQL(query: GraphQueryConfig): Promise<Record<string, unknown>[]> {
|
|
37
|
+
const rawEntity = query.entity as string
|
|
38
|
+
const canonicalEntity = Object.keys(ENTITY_TO_TABLE).find((k) => k.toLowerCase() === rawEntity.toLowerCase())
|
|
39
|
+
if (!canonicalEntity) {
|
|
40
|
+
throw new MantaError(
|
|
41
|
+
'INVALID_DATA',
|
|
42
|
+
`Unknown PostHog entity: ${rawEntity}. Known: ${Object.keys(ENTITY_TO_TABLE).join(', ')}`,
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
const entity = canonicalEntity
|
|
46
|
+
const table = ENTITY_TO_TABLE[entity]
|
|
47
|
+
|
|
48
|
+
const { host, personalApiKey } = readPostHogConnection()
|
|
49
|
+
const whereClause = translateFilters(entity, query.filters)
|
|
50
|
+
const limit = query.pagination?.limit ?? 100
|
|
51
|
+
const offset = query.pagination?.offset ?? 0
|
|
52
|
+
// Each ClickHouse table has its own time column — events.timestamp, persons.created_at.
|
|
53
|
+
// Pick the right one from DEFAULT_SORT, or skip ORDER BY entirely if no default is known.
|
|
54
|
+
const orderByClause = DEFAULT_SORT[entity] ? `ORDER BY ${DEFAULT_SORT[entity]}` : ''
|
|
55
|
+
|
|
56
|
+
const hogql = `SELECT * FROM ${table} ${whereClause} ${orderByClause} LIMIT ${limit} OFFSET ${offset}`
|
|
57
|
+
.replace(/\s+/g, ' ')
|
|
58
|
+
.trim()
|
|
59
|
+
|
|
60
|
+
const res = await fetch(`${host}/api/projects/@current/query/`, {
|
|
61
|
+
method: 'POST',
|
|
62
|
+
headers: {
|
|
63
|
+
Authorization: `Bearer ${personalApiKey}`,
|
|
64
|
+
'Content-Type': 'application/json',
|
|
65
|
+
},
|
|
66
|
+
body: JSON.stringify({ query: { kind: 'HogQLQuery', query: hogql } }),
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
if (!res.ok) {
|
|
70
|
+
throw new MantaError('INVALID_DATA', `PostHog HogQL returned ${res.status}: ${await res.text()}`)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const data = (await res.json()) as { results?: unknown[][]; columns?: string[] }
|
|
74
|
+
if (!data.results || !data.columns) return []
|
|
75
|
+
|
|
76
|
+
return data.results.map((row) => {
|
|
77
|
+
const obj: Record<string, unknown> = {}
|
|
78
|
+
data.columns?.forEach((col, idx) => {
|
|
79
|
+
obj[col] = row[idx]
|
|
80
|
+
})
|
|
81
|
+
return normalizeRow(entity, obj)
|
|
82
|
+
})
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Resolve posthogInsight via PostHog's REST endpoint (not HogQL — insights have their own API).
|
|
87
|
+
*/
|
|
88
|
+
export async function executeInsights(query: GraphQueryConfig): Promise<Record<string, unknown>[]> {
|
|
89
|
+
const { host, personalApiKey } = readPostHogConnection()
|
|
90
|
+
const params = new URLSearchParams()
|
|
91
|
+
params.set('limit', String(query.pagination?.limit ?? 100))
|
|
92
|
+
if (query.filters?.id) params.set('short_id', String(query.filters.id))
|
|
93
|
+
|
|
94
|
+
const res = await fetch(`${host}/api/projects/@current/insights/?${params}`, {
|
|
95
|
+
headers: { Authorization: `Bearer ${personalApiKey}` },
|
|
96
|
+
})
|
|
97
|
+
if (!res.ok) {
|
|
98
|
+
throw new MantaError('INVALID_DATA', `PostHog Insights API returned ${res.status}: ${await res.text()}`)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const data = (await res.json()) as { results?: Array<Record<string, unknown>> }
|
|
102
|
+
return (data.results ?? []).map((r) => ({
|
|
103
|
+
id: r.id,
|
|
104
|
+
name: r.name,
|
|
105
|
+
description: r.description,
|
|
106
|
+
shortId: r.short_id,
|
|
107
|
+
filters: r.filters,
|
|
108
|
+
createdAt: r.created_at,
|
|
109
|
+
updatedAt: r.updated_at,
|
|
110
|
+
}))
|
|
111
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// PostHog entity ↔ HogQL mapping — which ClickHouse tables + columns back each Manta entity.
|
|
2
|
+
|
|
3
|
+
/** Manta entity name → HogQL table name. */
|
|
4
|
+
export const ENTITY_TO_TABLE: Record<string, string> = {
|
|
5
|
+
posthogEvent: 'events',
|
|
6
|
+
posthogPerson: 'persons',
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/** Manta field name → HogQL column path (supports dotted access for properties). */
|
|
10
|
+
export const FIELD_MAP: Record<string, Record<string, string>> = {
|
|
11
|
+
posthogEvent: {
|
|
12
|
+
id: 'uuid',
|
|
13
|
+
event: 'event',
|
|
14
|
+
distinctId: 'distinct_id',
|
|
15
|
+
timestamp: 'timestamp',
|
|
16
|
+
properties: 'properties',
|
|
17
|
+
url: 'properties.$current_url',
|
|
18
|
+
personId: 'person_id',
|
|
19
|
+
},
|
|
20
|
+
posthogPerson: {
|
|
21
|
+
id: 'id',
|
|
22
|
+
distinctId: 'distinct_id',
|
|
23
|
+
email: 'properties.email',
|
|
24
|
+
name: 'properties.name',
|
|
25
|
+
createdAt: 'created_at',
|
|
26
|
+
properties: 'properties',
|
|
27
|
+
},
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** Filters supported per entity — anything else throws at query time. */
|
|
31
|
+
export const SUPPORTED_FILTERS: Record<string, string[]> = {
|
|
32
|
+
posthogEvent: ['event', 'distinctId', 'personId', 'timestamp', 'after', 'before'],
|
|
33
|
+
posthogPerson: ['email', 'distinctId', 'id'],
|
|
34
|
+
posthogInsight: ['id', 'shortId'],
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Default ORDER BY clause per entity. Each ClickHouse table has its own time column —
|
|
39
|
+
* `events.timestamp`, `persons.created_at` — and using the wrong one yields a 400
|
|
40
|
+
* "Unable to resolve field" error. Keyed by canonical Manta entity name.
|
|
41
|
+
*/
|
|
42
|
+
export const DEFAULT_SORT: Record<string, string> = {
|
|
43
|
+
posthogEvent: 'timestamp DESC',
|
|
44
|
+
posthogPerson: 'created_at DESC',
|
|
45
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// Manta query graph → HogQL SQL translator.
|
|
2
|
+
|
|
3
|
+
import { FIELD_MAP } from './schema'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Escape a raw value for safe inclusion in a HogQL string.
|
|
7
|
+
* Numbers and booleans are passed through, strings are single-quoted with ' → ''.
|
|
8
|
+
*/
|
|
9
|
+
export function escapeValue(v: unknown): string {
|
|
10
|
+
if (v === null || v === undefined) return 'NULL'
|
|
11
|
+
if (typeof v === 'number' || typeof v === 'boolean') return String(v)
|
|
12
|
+
return `'${String(v).replace(/'/g, "''")}'`
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Translate a Manta filter map into a HogQL `WHERE` clause.
|
|
17
|
+
* Only equality, IN (array value), and the special `after`/`before` timestamp filters are supported.
|
|
18
|
+
*/
|
|
19
|
+
export function translateFilters(entity: string, filters: Record<string, unknown> | undefined): string {
|
|
20
|
+
if (!filters || Object.keys(filters).length === 0) return ''
|
|
21
|
+
const fieldMap = FIELD_MAP[entity] ?? {}
|
|
22
|
+
const clauses: string[] = []
|
|
23
|
+
|
|
24
|
+
for (const [key, value] of Object.entries(filters)) {
|
|
25
|
+
if (key === 'after') {
|
|
26
|
+
clauses.push(`timestamp > ${escapeValue(value)}`)
|
|
27
|
+
continue
|
|
28
|
+
}
|
|
29
|
+
if (key === 'before') {
|
|
30
|
+
clauses.push(`timestamp < ${escapeValue(value)}`)
|
|
31
|
+
continue
|
|
32
|
+
}
|
|
33
|
+
const column = fieldMap[key] ?? key
|
|
34
|
+
if (Array.isArray(value)) {
|
|
35
|
+
const list = value.map(escapeValue).join(', ')
|
|
36
|
+
clauses.push(`${column} IN (${list})`)
|
|
37
|
+
} else {
|
|
38
|
+
clauses.push(`${column} = ${escapeValue(value)}`)
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return clauses.length > 0 ? `WHERE ${clauses.join(' AND ')}` : ''
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Normalize a raw HogQL result row (keyed by ClickHouse column names) into the Manta entity shape.
|
|
47
|
+
*/
|
|
48
|
+
export function normalizeRow(entity: string, row: Record<string, unknown>): Record<string, unknown> {
|
|
49
|
+
if (entity === 'posthogEvent') {
|
|
50
|
+
const props = (row.properties as Record<string, unknown> | null) ?? {}
|
|
51
|
+
return {
|
|
52
|
+
id: row.uuid ?? row.id,
|
|
53
|
+
event: row.event,
|
|
54
|
+
distinctId: row.distinct_id,
|
|
55
|
+
timestamp: row.timestamp,
|
|
56
|
+
properties: props,
|
|
57
|
+
url: props.$current_url ?? null,
|
|
58
|
+
personId: row.person_id ?? null,
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
if (entity === 'posthogPerson') {
|
|
62
|
+
const props = (row.properties as Record<string, unknown> | null) ?? {}
|
|
63
|
+
return {
|
|
64
|
+
id: row.id,
|
|
65
|
+
distinctId: row.distinct_id,
|
|
66
|
+
email: (props.email as string | undefined) ?? null,
|
|
67
|
+
name: (props.name as string | undefined) ?? null,
|
|
68
|
+
createdAt: row.created_at,
|
|
69
|
+
properties: props,
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return row
|
|
73
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// Generated by ts-to-zod
|
|
2
|
+
import { z } from 'zod'
|
|
3
|
+
|
|
4
|
+
export const postHogCaptureInputSchema = z.object({
|
|
5
|
+
distinctId: z.string(),
|
|
6
|
+
event: z.string(),
|
|
7
|
+
properties: z.record(z.string(), z.unknown()).optional(),
|
|
8
|
+
timestamp: z.date().optional(),
|
|
9
|
+
uuid: z.string().optional(),
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
export const postHogIdentifyInputSchema = z.object({
|
|
13
|
+
distinctId: z.string(),
|
|
14
|
+
properties: z.record(z.string(), z.unknown()).optional(),
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
const _assertCaptureMatchesSdkSchema = z.any()
|
|
18
|
+
|
|
19
|
+
const _assertIdentifyMatchesSdkSchema = z.any()
|
|
20
|
+
|
|
21
|
+
export const postHogEventSchema = z.object({
|
|
22
|
+
uuid: z.string(),
|
|
23
|
+
event: z.string(),
|
|
24
|
+
distinctId: z.string(),
|
|
25
|
+
timestamp: z.string(),
|
|
26
|
+
properties: z.record(z.string(), z.unknown()),
|
|
27
|
+
personId: z.string().nullable(),
|
|
28
|
+
url: z.string().nullable(),
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
export const postHogPersonSchema = z.object({
|
|
32
|
+
id: z.string(),
|
|
33
|
+
distinctId: z.string(),
|
|
34
|
+
email: z.string().nullable(),
|
|
35
|
+
name: z.string().nullable(),
|
|
36
|
+
createdAt: z.string(),
|
|
37
|
+
properties: z.record(z.string(), z.unknown()),
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
export const postHogInsightSchema = z.object({
|
|
41
|
+
id: z.number(),
|
|
42
|
+
shortId: z.string().nullable(),
|
|
43
|
+
name: z.string(),
|
|
44
|
+
description: z.string().nullable(),
|
|
45
|
+
filters: z.record(z.string(), z.unknown()),
|
|
46
|
+
createdAt: z.string(),
|
|
47
|
+
updatedAt: z.string().nullable(),
|
|
48
|
+
})
|