UNPKG

@r-delfino/mux-sync-engine

Version:

Mux Sync Engine to sync Mux data based on webhooks to Postgres

127 lines (120 loc) 4.13 kB
import { Mux } from '@mux/mux-node'; import pg, { QueryResult } from 'pg'; import pino from 'pino'; import { HeadersLike } from '@mux/mux-node/core'; interface EntitySchema { readonly properties: string[]; } type PostgresConfig = { databaseUrl: string; schema: string; maxConnections?: number; }; declare class PostgresClient { private config; pool: pg.Pool; constructor(config: PostgresConfig); delete(table: string, id: string): Promise<boolean>; query(text: string, params?: string[]): Promise<QueryResult>; upsertMany<T extends { [Key: string]: any; }>(entries: T[], table: string, tableSchema: EntitySchema, options?: { conflict?: string; }): Promise<T[]>; findMissingEntries(table: string, ids: string[]): Promise<string[]>; /** * Returns an (yesql formatted) upsert function based on the key/vals of an object. * eg, * insert into customers ("id", "name") * values (:id, :name) * on conflict (id) * do update set ( * "id" = :id, * "name" = :name * ) */ private constructUpsertSql; /** * For array object field like invoice.custom_fields * ex: [{"name":"Project name","value":"Test Project"}] * * we need to stringify it first cos passing array object directly will end up with * { * invalid input syntax for type json * detail: 'Expected ":", but found "}".', * where: 'JSON data, line 1: ...\\":\\"Project name\\",\\"value\\":\\"Test Project\\"}"}', * } */ private cleanseArrayField; } type MuxSyncConfig = { /** Postgres database URL including authentication */ databaseUrl: string; /** Database schema name. */ schema?: string; /** Mux token ID used to authenticate requests to the Mux API. */ muxTokenId: string; /** Mux token secret used to authenticate requests to the Mux API. */ muxTokenSecret: string; /** Mux webhook secret used to verify the signature of webhook events. */ muxWebhookSecret: string; /** * If true, the sync engine will backfill related entities, i.e. when a invoice webhook comes in, it ensures that the customer is present and synced. * This ensures foreign key integrity, but comes at the cost of additional queries to the database (and added latency for Stripe calls if the entity is actually missing). */ backfillRelatedEntities?: boolean; /** * If true, the webhook data is not used and instead the webhook is just a trigger to fetch the entity from Stripe again. This ensures that a race condition with failed webhooks can never accidentally overwrite the data with an older state. * * Default: false */ revalidateEntityViaMuxApi?: boolean; maxPostgresConnections?: number; logger?: pino.Logger; }; type SyncObject = 'all' | 'mux_assets' | 'mux_live_streams'; interface Sync { synced: number; } interface SyncBackfill { muxAssets?: Sync; muxLiveStreams?: Sync; } interface SyncBackfillParams { created?: { /** * Minimum value to filter by (exclusive) */ gt?: number; /** * Minimum value to filter by (inclusive) */ gte?: number; /** * Maximum value to filter by (exclusive) */ lt?: number; /** * Maximum value to filter by (inclusive) */ lte?: number; }; object?: SyncObject; backfillRelatedEntities?: boolean; } declare class MuxSync { private config; mux: Mux; postgresClient: PostgresClient; constructor(config: MuxSyncConfig); processWebhook(payload: string, headers: HeadersLike): Promise<void>; private fetchOrUseWebhookData; syncBackfill(params?: SyncBackfillParams): Promise<SyncBackfill>; private upsertAssets; } type MigrationConfig = { databaseUrl: string; logger?: pino.Logger; }; declare function runMigrations(config: MigrationConfig): Promise<void>; export { MuxSync, type MuxSyncConfig, type Sync, type SyncBackfill, type SyncBackfillParams, type SyncObject, runMigrations };