@r-delfino/mux-sync-engine
Version:
Mux Sync Engine to sync Mux data based on webhooks to Postgres
148 lines (141 loc) • 5.06 kB
TypeScript
import { Mux } from '@mux/mux-node';
import pg, { QueryResult } from 'pg';
import { HeadersLike } from '@mux/mux-node/core';
interface EntitySchema$1 {
readonly properties: string[];
}
type PostgresConfig = {
databaseUrl: string;
schema: string;
maxConnections?: number;
};
declare class PostgresClient {
private config;
pool: pg.Pool;
constructor(config: PostgresConfig);
deleteByField(table: string, field: string, value: string): Promise<boolean>;
query(text: string, params?: any[]): Promise<QueryResult>;
upsertMany<T extends {
[Key: string]: any;
}>(entries: T[], table: string, tableSchema: EntitySchema$1, options?: {
conflict?: string;
}): Promise<T[]>;
findMissingEntries(idField: string | undefined, 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
* 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 Logger = Pick<globalThis.Console, 'info' | 'error' | 'warn' | 'debug'>;
type MuxSyncConfig = {
/** Postgres database URL including authentication */
databaseUrl: 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 Upload webhook comes in, it ensures that the asset is present and synced.
* This ensures foreign key integrity, but comes at the cost of additional queries to the database (and added latency for Mux 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 Mux 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;
/** Optional logger. If not provided, `console` will be used. */
logger?: Logger;
};
type SyncObject = 'all' | 'mux_assets' | 'mux_live_streams' | 'mux_uploads';
interface Sync {
synced: number;
}
interface SyncBackfill {
muxAssets?: Sync;
muxLiveStreams?: Sync;
muxUploads?: Sync;
}
interface SyncBackfillParams {
object?: SyncObject;
}
interface MuxListResponse<T> {
data: T[];
next_cursor?: string;
}
interface SimulcastTargetData {
live_stream_id?: string;
id?: string;
[key: string]: unknown;
}
interface StaticRenditionData {
asset_id?: string;
id?: string;
[key: string]: unknown;
}
interface TrackData extends Record<string, unknown> {
asset_id?: string;
id?: string;
}
type TransformFunction<T, R = Record<string, unknown>> = (entity: T) => R;
interface UpsertResult {
id: string;
[key: string]: unknown;
}
type EntitySchema = EntitySchema$1;
declare class MuxSync {
private config;
mux: Mux;
postgresClient: PostgresClient;
private logger;
constructor(config: MuxSyncConfig);
processWebhook(payload: string, headers: HeadersLike): Promise<void>;
syncBackfill(params?: SyncBackfillParams): Promise<SyncBackfill>;
private fetchOrUseWebhookData;
private upsertAssets;
private genericSync;
private syncMuxAssets;
private upsertEntitiesWithRelatedAssets;
private upsertLiveStreams;
private upsertUploads;
private syncMuxLiveStreams;
private syncMuxUploads;
private handleAssetUpdateEvent;
private handleAssetTrackEvent;
private handleLiveStreamUpdateEvent;
private handleLiveStreamSimulcastTargetEvent;
private handleAssetStaticRenditionEvent;
private deleteAsset;
private deleteLiveStream;
private upsertWebhookEvent;
}
type MigrationConfig = {
databaseUrl: string;
logger?: Logger;
};
declare function runMigrations(config: MigrationConfig): Promise<void>;
export { type EntitySchema, type Logger, type MuxListResponse, MuxSync, type MuxSyncConfig, type SimulcastTargetData, type StaticRenditionData, type Sync, type SyncBackfill, type SyncBackfillParams, type SyncObject, type TrackData, type TransformFunction, type UpsertResult, runMigrations };