# Server-side Spreadsheet

Use `Spreadsheet` from `libs/spreadsheet-state/interface/spreadsheet-interface.ts` when you want to apply spreadsheet operations on the server (API routes, workers, job processors), then evaluate formulas before persisting or broadcasting changes.

## Import

Use the server entrypoint:

```ts
import { Spreadsheet } from "@rowsncolumns/spreadsheet-state/server";
```

## 1) Initialize state

```ts
import type { CellData, Sheet, TableView } from "@rowsncolumns/spreadsheet";
import type { SheetData } from "@rowsncolumns/spreadsheet-state";
import { Spreadsheet } from "@rowsncolumns/spreadsheet-state/server";

const spreadsheet = new Spreadsheet();

const sheets: Sheet[] = [
  { sheetId: 1, rowCount: 200, columnCount: 26, title: "Sheet1" },
];
const sheetData: SheetData<CellData> = { 1: [] };
const tables: TableView[] = [];

spreadsheet.sheets = sheets;
spreadsheet.sheetData = sheetData;
spreadsheet.tables = tables;
```

## 2) Apply updates

Use `changeBatch` for cell values/formulas (single or multi-range):

```ts
spreadsheet.changeBatch(
  1,
  {
    startRowIndex: 1,
    endRowIndex: 1,
    startColumnIndex: 1,
    endColumnIndex: 1,
  },
  [[10]],
);

spreadsheet.changeBatch(
  1,
  {
    startRowIndex: 1,
    endRowIndex: 1,
    startColumnIndex: 2,
    endColumnIndex: 2,
  },
  [["=A1*2"]],
);
```

You can also use structural APIs like `insertRow`, `insertColumn`, `deleteRow`, `deleteColumn`, `changeFormatting`, `updateTable`, etc. on the same `Spreadsheet` instance.

## 3) Run evaluation

After backend edits, explicitly flush calculations:

```ts
const results = await spreadsheet.calculatePending();
```

Useful variants:

* `await spreadsheet.calculatePending()`: Runs only queued operations and returns calculated result entries.
* `await spreadsheet.flushCalculations()`: Runs queued operations but does not return result entries.
* `await spreadsheet.calculateAll()`: Scans current `sheetData` formulas and evaluates them.

If you replace `sheetData` directly (outside `changeBatch`), call `calculateAll()` for a full formula pass, or call `rebuildGraph()` and enqueue explicit operations before `calculatePending()`.

## 4) Read updated values

`calculatePending`/`flushCalculations`/`calculateAll` apply results back into `spreadsheet.sheetData` via the internal calculation pipeline.

```ts
const cellB1 = spreadsheet.sheetData[1]?.[1]?.values?.[2];
```

## 5) Persist or broadcast patches

Every mutation pushes history patches that you can forward to persistence/collab layers.

```ts
const patchTuples = spreadsheet.getPatchTuples(); // for undo/redo style patch consumers
const fullStatePatches = await spreadsheet.generateStatePatches(); // full-state patch export
spreadsheet.clearPatches(); // optional reset after persisting/broadcasting
```

## Worker configuration (recommended)

For backend runtimes, provide a calculation worker explicitly:

```ts
import { Worker } from "node:worker_threads";
import { Spreadsheet } from "@rowsncolumns/spreadsheet-state/server";

const spreadsheet = new Spreadsheet({
  createCalculationWorker: () =>
    new Worker(require.resolve("@rowsncolumns/calculation-worker/worker")),
});
```
