Skip to main content

sync API

Sync provides a batch upsert runner and shared SyncTarget types.

npm install @rowops/sync

Core API

runSync

Run Sync against a target.

import { runSync } from "@rowops/sync";

const summary = await runSync(sourceIterator, target, {
context: { schemaId, projectId, runId },
batchSize: 1000,
concurrency: 1,
maxRetries: 2,
onProgress: (progress) => console.log(progress),
});

Types

SyncTarget

interface SyncTarget<Row = Record<string, unknown>> {
id: string;
label: string;
description?: string;
sendBatch: (batch: Row[], ctx: SyncTargetContext) => Promise<void>;
}

SyncTargetContext

interface SyncTargetContext {
schemaId: string;
projectId?: string;
runId?: string;
}

SyncSourceMode

type SyncSourceMode = "full" | "diff";

SyncRunProgress

interface SyncRunProgress {
batchIndex: number;
batchCount?: number;
sentRows: number;
totalRows?: number;
}

SyncRunSummary

interface SyncRunSummary {
targetId: string;
sourceMode: SyncSourceMode;
totalRows: number;
sentRows: number;
batchCount: number;
durationMs: number;
}

SyncBatchError

Thrown when a batch fails after retries.

class SyncBatchError extends Error {
batch: Record<string, unknown>[];
batchIndex: number;
attempts: number;
maxRetries: number;
targetId: string;
}

Usage with Importer

import { RowOpsImporter } from "@rowops/importer";

<RowOpsImporter
projectId="proj_xxx"
schemaId="contacts"
publishableKey="pk_xxx"
syncTargets={[
{
id: "staging",
label: "Staging API",
sendBatch: async (rows, ctx) => {
await fetch("/api/sync", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
schemaId: ctx.schemaId,
projectId: ctx.projectId,
runId: ctx.runId,
rows,
}),
});
},
},
]}
syncOptions={{ batchSize: 1000, maxConcurrency: 1 }}
onSyncComplete={(result) => {
console.log(`Synced ${result.sentRows}/${result.totalRows}`);
}}
/>