mirror of
https://github.com/PostHog/posthog.git
synced 2024-11-25 11:17:50 +01:00
0fdb1e0fe3
* start passing context around instead of multiple parameters * start passing a result and context back from conversions * even more using the context and the results * get id sequences under control * manually run prettier * add lint staged rules for ee TS code * remove console logs * start tracking ids as they are processedD * Add a new test case and so update _all_ of the ids :/ * don't process the same add or update id more than once * refactor similar closer together * move keyboard style override into context * snapshots * remove constant * need to fangle context in case select options ever starts to change it
83 lines
2.8 KiB
TypeScript
83 lines
2.8 KiB
TypeScript
import { eventWithTime } from '@rrweb/types'
|
|
import { captureException, captureMessage } from '@sentry/react'
|
|
import Ajv, { ErrorObject } from 'ajv'
|
|
|
|
import { mobileEventWithTime } from './mobile.types'
|
|
import mobileSchema from './schema/mobile/rr-mobile-schema.json'
|
|
import webSchema from './schema/web/rr-web-schema.json'
|
|
import { makeCustomEvent, makeFullEvent, makeIncrementalEvent, makeMetaEvent } from './transformer/transformers'
|
|
|
|
const ajv = new Ajv({
|
|
allowUnionTypes: true,
|
|
}) // options can be passed, e.g. {allErrors: true}
|
|
|
|
const transformers: Record<number, (x: any) => eventWithTime> = {
|
|
2: makeFullEvent,
|
|
3: makeIncrementalEvent,
|
|
4: makeMetaEvent,
|
|
5: makeCustomEvent,
|
|
}
|
|
|
|
const mobileSchemaValidator = ajv.compile(mobileSchema)
|
|
|
|
export function validateFromMobile(data: unknown): {
|
|
isValid: boolean
|
|
errors: ErrorObject[] | null | undefined
|
|
} {
|
|
const isValid = mobileSchemaValidator(data)
|
|
return {
|
|
isValid,
|
|
errors: isValid ? null : mobileSchemaValidator.errors,
|
|
}
|
|
}
|
|
|
|
const webSchemaValidator = ajv.compile(webSchema)
|
|
|
|
function couldBeEventWithTime(x: unknown): x is eventWithTime | mobileEventWithTime {
|
|
return typeof x === 'object' && x !== null && 'type' in x && 'timestamp' in x
|
|
}
|
|
|
|
export function transformEventToWeb(event: unknown, validateTransformation?: boolean): eventWithTime {
|
|
// the transformation needs to never break a recording itself
|
|
// so, we default to returning what we received
|
|
// replacing it only if there's a valid transformation
|
|
let result = event as eventWithTime
|
|
try {
|
|
if (couldBeEventWithTime(event)) {
|
|
const transformer = transformers[event.type]
|
|
if (transformer) {
|
|
const transformed = transformer(event)
|
|
if (validateTransformation) {
|
|
validateAgainstWebSchema(transformed)
|
|
}
|
|
result = transformed
|
|
}
|
|
} else {
|
|
captureMessage(`No type in event`, { extra: { event } })
|
|
}
|
|
} catch (e) {
|
|
captureException(e, { extra: { event } })
|
|
}
|
|
return result
|
|
}
|
|
|
|
export function transformToWeb(mobileData: (eventWithTime | mobileEventWithTime)[]): eventWithTime[] {
|
|
return mobileData.reduce((acc, event) => {
|
|
const transformed = transformEventToWeb(event)
|
|
acc.push(transformed ? transformed : (event as eventWithTime))
|
|
return acc
|
|
}, [] as eventWithTime[])
|
|
}
|
|
|
|
export function validateAgainstWebSchema(data: unknown): boolean {
|
|
const validationResult = webSchemaValidator(data)
|
|
if (!validationResult) {
|
|
// we are passing all data through this validation now and don't know how safe the schema is
|
|
captureMessage('transformation did not match schema', {
|
|
extra: { data, errors: webSchemaValidator.errors },
|
|
})
|
|
}
|
|
|
|
return validationResult
|
|
}
|