# core/coordinators/snapshot.coordinator.ts

> 61 lines of code and 13 definitions.

Tree: Project Scripts
Language: typescript
Layer: application
Canonical: https://banes-lab.com/anatomy/scripts#file-scripts-core-coordinators-snapshot-coordinator-ts
Source text: https://banes-lab.com/source/scripts/core/coordinators/snapshot.coordinator.ts.txt

Listed in [core/coordinators](https://banes-lab.com/api/source/scripts/core/coordinators.md), after [core/coordinators/route.coordinator.ts](https://banes-lab.com/source/scripts/core/coordinators/route.coordinator.ts.md) and before [core/coordinators/viewport.coordinator.ts](https://banes-lab.com/source/scripts/core/coordinators/viewport.coordinator.ts.md).

## Definitions

- `settleAndClick` (lexical_declaration, line 13)
- `captureThrough` (lexical_declaration, line 27)
- `capturePage` (lexical_declaration, line 45, exported)
- `HERE` (lexical_declaration, line 11)
- `[x = 0, y = 0]` (lexical_declaration, line 19)
- `spot` (lexical_declaration, line 20)
- `{ data }` (lexical_declaration, line 41)
- `profile` (lexical_declaration, line 46, exported)
- `child` (lexical_declaration, line 47, exported)
- `endpoint` (lexical_declaration, line 54, exported)
- `session` (lexical_declaration, line 59, exported)
- `data` (lexical_declaration, line 60, exported)
- `records` (lexical_declaration, line 61, exported)

## Contained in

- [core/coordinators](https://banes-lab.com/anatomy/scripts/folder-scripts-core-coordinators.md)

## Uses

- [configuration/strings/snapshot.strings.ts](https://banes-lab.com/source/scripts/configuration/strings/snapshot.strings.ts.md)
- [core/persistence/snapshot.persistence.ts](https://banes-lab.com/source/scripts/core/persistence/snapshot.persistence.ts.md)

## Linked from

- [configuration/strings](https://banes-lab.com/anatomy/scripts/folder-scripts-configuration-strings.md)
- [core/coordinators](https://banes-lab.com/anatomy/scripts/folder-scripts-core-coordinators.md)
- [core/persistence](https://banes-lab.com/anatomy/scripts/folder-scripts-core-persistence.md)

## Source

```typescript
import { NO_DEVTOOLS, clickedLine } from "#configuration/strings/snapshot.strings";
import { devtoolsEndpoint, openSession } from "@banes-lab/build-scripts/core/adapters/browser.adapter.ts";
import { dirname, resolve } from "node:path";
import { freshProfile, launchBrowser, settleBrowser } from "@banes-lab/build-scripts/core/factories/browser.factory.ts";
import type { Session } from "@banes-lab/build-scripts/types/browser.types.ts";
import type { SnapshotOptions } from "#types/snapshot.types";
import process from "node:process";
import { wait } from "@banes-lab/build-scripts/core/timers/base.timer.ts";
import { writeArtifacts } from "#core/persistence/snapshot.persistence";

const HERE = ".";

const settleAndClick = async function settleAndClick(session: Session, options: SnapshotOptions): Promise<void> {
    if (options.clickAt === null) {
        await wait(options.settleMs);
        return;
    }
    await wait(Math.min(options.clickAfterMs, options.settleMs));
    const [x = 0, y = 0] = options.clickAt;
    const spot = { button: "left", clickCount: 1, x, y };
    await session.send("Input.dispatchMouseEvent", { ...spot, type: "mousePressed" });
    await session.send("Input.dispatchMouseEvent", { ...spot, type: "mouseReleased" });
    process.stdout.write(clickedLine(x, y));
    await wait(Math.max(0, options.settleMs - options.clickAfterMs));
};

const captureThrough = async function captureThrough(session: Session, options: SnapshotOptions): Promise<string> {
    await session.send("Page.enable");
    await session.send("Runtime.enable");
    await session.send("Emulation.setDeviceMetricsOverride", {
        deviceScaleFactor: 1,
        height: options.height,
        mobile: false,
        width: options.width,
    });
    await session.send("Page.navigate", { url: options.url });
    await settleAndClick(session, options);
    if (options.out === null) {
        return "";
    }
    const { data } = await session.send("Page.captureScreenshot", { format: "png" });
    return typeof data === "string" ? data : "";
};

export const capturePage = async function capturePage(binary: string, options: SnapshotOptions): Promise<boolean> {
    const profile = freshProfile(resolve(dirname(options.out ?? options.log ?? HERE)));
    const child = launchBrowser(binary, {
        height: options.height,
        profileDir: profile,
        software: options.software,
        width: options.width,
    });
    return settleBrowser(child, async () => {
        const endpoint = await devtoolsEndpoint(profile, options.timeoutMs);
        if (endpoint === null) {
            process.stderr.write(NO_DEVTOOLS);
            return false;
        }
        const session = await openSession(endpoint, true);
        const data = await captureThrough(session, options);
        const records = session.records();
        session.close();
        return writeArtifacts(options, data, records);
    });
};
```
