> ## Documentation Index
> Fetch the complete documentation index at: https://stratasync.blode.md/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Transactions

Every local change becomes a `Transaction` that flows through the outbox, travels to the server, and gets confirmed by the sync protocol.

## Transaction interface

Every mutation conforms to this structure:

```ts
interface Transaction {
  clientTxId: string;
  clientId: string;
  modelName: string;
  modelId: string;
  action: TransactionAction;
  payload: Record<string, unknown>;
  original?: Record<string, unknown>;
  state: TransactionState;
  createdAt: number;
  retryCount: number;
  lastError?: string;
  syncIdNeededForCompletion?: number;
  batchIndex?: number;
}
```

### TransactionAction

| Action    | Code  | Description                           |
| --------- | ----- | ------------------------------------- |
| Insert    | `"I"` | Creates a new model instance.         |
| Update    | `"U"` | Modifies fields on an existing model. |
| Delete    | `"D"` | Permanently removes a model instance. |
| Archive   | `"A"` | Soft-deletes by setting `archivedAt`. |
| Unarchive | `"V"` | Restores a soft-deleted model.        |

### TransactionState

| State            | Description                                                     |
| ---------------- | --------------------------------------------------------------- |
| `"queued"`       | In the local outbox, not yet sent.                              |
| `"sent"`         | Sent to the server, awaiting confirmation.                      |
| `"awaitingSync"` | Server confirmed, waiting for the sync ID via the delta stream. |
| `"completed"`    | Fully synced.                                                   |
| `"failed"`       | Failed permanently after all retries.                           |

## Creating transactions

### createTransaction

General-purpose factory; all other helpers delegate to it.

```ts
import { createTransaction } from "@stratasync/core";

const tx = createTransaction({
  clientId: "client-abc",
  modelName: "Task",
  modelId: "task-123",
  action: "U",
  payload: { title: "Updated title" },
  original: { title: "Original title" },
});
```

**CreateTransactionOptions:**

| Field       | Type                      | Required | Description                 |
| ----------- | ------------------------- | -------- | --------------------------- |
| `clientId`  | `string`                  | Yes      | Client instance ID.         |
| `modelName` | `string`                  | Yes      | Registered model name.      |
| `modelId`   | `string`                  | Yes      | Model instance ID.          |
| `action`    | `TransactionAction`       | Yes      | Mutation type.              |
| `payload`   | `Record<string, unknown>` | Yes      | Changed data.               |
| `original`  | `Record<string, unknown>` | No       | Original data for rollback. |

### createInsertTransaction

Creates an insert (`"I"`) transaction.

```ts
import { createInsertTransaction } from "@stratasync/core";

const tx = createInsertTransaction("client-abc", "Task", "task-123", {
  title: "New Task",
  status: "todo",
  priority: 0,
  projectId: "project-456",
});
```

### createUpdateTransaction

Creates an update (`"U"`) transaction with changed fields and originals.

```ts
import { createUpdateTransaction } from "@stratasync/core";

const tx = createUpdateTransaction(
  "client-abc",
  "Task",
  "task-123",
  { title: "Updated title" },
  { title: "Original title" }
);
```

### createDeleteTransaction

Creates a delete (`"D"`) transaction. Pass original data so undo can re-create the model.

```ts
import { createDeleteTransaction } from "@stratasync/core";

const tx = createDeleteTransaction("client-abc", "Task", "task-123", {
  title: "Task to delete",
  status: "done",
});
```

### createArchiveTransaction and createUnarchiveTransaction

Archive (`"A"`) soft-deletes a model by setting `archivedAt`. Unarchive (`"V"`) restores it.

```ts
import {
  createArchiveTransaction,
  createUnarchiveTransaction,
} from "@stratasync/core";

// Soft-delete
const archiveTx = createArchiveTransaction("client-abc", "Task", "task-123", {
  original: { archivedAt: undefined },
  archivedAt: "2025-01-15T10:30:00.000Z",
});

// Restore
const unarchiveTx = createUnarchiveTransaction(
  "client-abc",
  "Task",
  "task-123",
  {
    original: { archivedAt: "2025-01-15T10:30:00.000Z" },
  }
);
```

### createUndoTransaction

Creates the inverse transaction. Returns `null` if the transaction can't be undone (for example, a delete without original data).

```ts
import { createUndoTransaction } from "@stratasync/core";

const originalTx = createUpdateTransaction(
  "client-abc",
  "Task",
  "task-123",
  { title: "New" },
  { title: "Old" }
);

const undoTx = createUndoTransaction(originalTx);
// undoTx.action === "U"
// undoTx.payload === { title: "Old" }
// undoTx.original === { title: "New" }
```

**Undo mapping:**

| Original action   | Undo action       | Notes                                                         |
| ----------------- | ----------------- | ------------------------------------------------------------- |
| Insert (`"I"`)    | Delete (`"D"`)    | Deletes the inserted model.                                   |
| Delete (`"D"`)    | Insert (`"I"`)    | Re-creates with original data. Returns `null` if no original. |
| Update (`"U"`)    | Update (`"U"`)    | Swaps payload and original. Returns `null` if no original.    |
| Archive (`"A"`)   | Unarchive (`"V"`) | Restores the model.                                           |
| Unarchive (`"V"`) | Archive (`"A"`)   | Re-archives the model.                                        |

## Batching

### createTransactionBatch

Groups transactions into a batch for atomic server submission.

```ts
import {
  createTransactionBatch,
  createInsertTransaction,
  createUpdateTransaction,
} from "@stratasync/core";

const batch = createTransactionBatch([
  createInsertTransaction("client-abc", "Task", "task-1", { title: "Task 1" }),
  createUpdateTransaction(
    "client-abc",
    "Project",
    "proj-1",
    { taskCount: 5 },
    { taskCount: 4 }
  ),
]);
// batch.batchId: string
// batch.transactions: Transaction[]
// batch.createdAt: number
```

**TransactionBatch interface:**

```ts
interface TransactionBatch {
  batchId: string;
  transactions: Transaction[];
  createdAt: number;
}
```

## Serialization

Serialize transactions to a compact format for storage or transport.

### Single transactions

```ts
import {
  serializeTransaction,
  deserializeTransaction,
  transactionToJson,
  transactionFromJson,
} from "@stratasync/core";

// To compact object
const serialized = serializeTransaction(tx);
const restored = deserializeTransaction(serialized);

// To/from JSON string
const json = transactionToJson(tx);
const parsed = transactionFromJson(json);
```

### Batches

```ts
import {
  serializeBatch,
  deserializeBatch,
  batchToJson,
  batchFromJson,
} from "@stratasync/core";

// To compact object
const serialized = serializeBatch(batch);
const restored = deserializeBatch(serialized);

// To/from JSON string
const json = batchToJson(batch);
const parsed = batchFromJson(json);
```

### Serialized format

Short keys minimize payload size.

| Transaction field           | Serialized key |
| --------------------------- | -------------- |
| `clientTxId`                | `cid`          |
| `clientId`                  | `cli`          |
| `modelName`                 | `m`            |
| `modelId`                   | `mid`          |
| `action`                    | `a`            |
| `payload`                   | `p`            |
| `original`                  | `o`            |
| `state`                     | `s`            |
| `createdAt`                 | `t`            |
| `retryCount`                | `r`            |
| `lastError`                 | `e`            |
| `syncIdNeededForCompletion` | `s2`           |
| `batchIndex`                | `b`            |

## Server result types

Returned after submitting transactions:

### TransactionResult

```ts
interface TransactionResult {
  clientTxId: string;
  success: boolean;
  syncId?: number;
  error?: string;
  errorCode?: string;
}
```

### MutateResult

```ts
interface MutateResult {
  success: boolean;
  lastSyncId: number;
  results: TransactionResult[];
}
```