# runtime/entrypoints/stage.entrypoint.ts

> 90 lines of code and 16 definitions.

Tree: Bane's Lab Social Share
Language: typescript
Layer: runtime
Canonical: https://banes-lab.com/anatomy/social-share#file-social-share-runtime-entrypoints-stage-entrypoint-ts
Source text: https://banes-lab.com/source/social-share/runtime/entrypoints/stage.entrypoint.ts.txt

Listed in [runtime/entrypoints](https://banes-lab.com/api/source/social-share/runtime/entrypoints.md), after [runtime/entrypoints/card.entrypoint.ts](https://banes-lab.com/source/social-share/runtime/entrypoints/card.entrypoint.ts.md) and before [runtime/entrypoints/validation.entrypoint.ts](https://banes-lab.com/source/social-share/runtime/entrypoints/validation.entrypoint.ts.md).

## Definitions

- `render` (lexical_declaration, line 45)
- `nextPaint` (lexical_declaration, line 31)
- `showCapture` (lexical_declaration, line 41)
- `messageOf` (lexical_declaration, line 27)
- `mounted` (lexical_declaration, line 43)
- `captureTarget` (lexical_declaration, line 58)
- `card` (lexical_declaration, line 59)
- `profileId` (lexical_declaration, line 60)
- `captured` (lexical_declaration, line 61)
- `profile` (lexical_declaration, line 65)
- `host` (lexical_declaration, line 72)
- `query` (lexical_declaration, line 76)
- `target` (lexical_declaration, line 79)
- `loaded` (lexical_declaration, line 86)
- `findings` (lexical_declaration, line 87)
- `stopGrid` (lexical_declaration, line 93)

## Contained in

- [runtime/entrypoints](https://banes-lab.com/anatomy/social-share/folder-social-share-runtime-entrypoints.md)

## Uses

- [core/evaluators/card.evaluator.ts](https://banes-lab.com/source/social-share/core/evaluators/card.evaluator.ts.md)
- [core/timers/stage.timer.ts](https://banes-lab.com/source/social-share/core/timers/stage.timer.ts.md)

## Linked from

- [core/evaluators](https://banes-lab.com/anatomy/social-share/folder-social-share-core-evaluators.md)
- [core/timers](https://banes-lab.com/anatomy/social-share/folder-social-share-core-timers.md)
- [runtime/entrypoints](https://banes-lab.com/anatomy/social-share/folder-social-share-runtime-entrypoints.md)

## Source

```typescript
import "@banes-lab/web/presentation/tokens/base.tokens.css";
import "@banes-lab/web/presentation/tokens/asset.tokens.css";
import "@banes-lab/web/presentation/tokens/page.tokens.css";
import "@banes-lab/web/presentation/generated/icon.tokens.generated.css";
import "@banes-lab/web/presentation/styles/element.style.css";
import "../../core/styles/stage.style.css";
import {
    CARD_PARAMETER,
    ERROR_FLAG,
    PROFILE_PARAMETER,
    READY_FLAG,
    RENDER_HOOK,
    STAGE_ID,
    STAGE_STEPS,
    STEP_FLAG,
} from "#configuration/constants/card.constants";
import type { CardSpec, Profile } from "#types/card.types";
import { NO_STAGE, SUBJECT_SEPARATOR, UNKNOWN_CARD, UNKNOWN_STAGE_PROFILE } from "#configuration/strings/card.strings";
import { PROFILES } from "#configuration/configs/card.config";
import { getCard } from "#core/registries/card.registry";
import { loadCards } from "#core/loaders/card.loader";
import { mountCard } from "#core/renderers/stage.renderer";
import { renderGrid } from "#core/renderers/grid.renderer";
import { resolveCard } from "#core/evaluators/card.evaluator";
import { validateCards } from "#core/validators/card.validator";

const messageOf = function messageOf(failure: unknown): string {
    return failure instanceof Error ? failure.message : String(failure);
};

const nextPaint = async function nextPaint(): Promise<void> {
    return new Promise((settle) => {
        requestAnimationFrame(() => {
            requestAnimationFrame(() => {
                settle();
            });
        });
    });
};

const showCapture = async function showCapture(host: HTMLElement, spec: CardSpec, profile: Profile): Promise<void> {
    Reflect.set(window, STEP_FLAG, STAGE_STEPS.mounting);
    const mounted = mountCard(host, resolveCard(spec, profile, spec.timeline.keyFrame));
    await mounted.ready();
    const render = async (index: number): Promise<boolean> => {
        await mounted.paint(resolveCard(spec, profile, index));
        await nextPaint();
        return true;
    };
    Reflect.set(window, RENDER_HOOK, render);
    Reflect.set(window, STEP_FLAG, STAGE_STEPS.fonts);
    await document.fonts.ready;
    Reflect.set(window, STEP_FLAG, STAGE_STEPS.painting);
    await render(spec.timeline.keyFrame);
    Reflect.set(window, READY_FLAG, true);
};

const captureTarget = function captureTarget(query: URLSearchParams): { spec: CardSpec; profile: Profile } {
    const card = query.get(CARD_PARAMETER) ?? "";
    const profileId = query.get(PROFILE_PARAMETER) ?? "";
    const captured = getCard(card);
    if (captured === undefined) {
        throw new Error(UNKNOWN_CARD + SUBJECT_SEPARATOR + card);
    }
    const profile = PROFILES.find((candidate) => candidate.id === profileId);
    if (profile === undefined) {
        throw new Error(UNKNOWN_STAGE_PROFILE + SUBJECT_SEPARATOR + profileId);
    }
    return { profile, spec: captured.spec };
};

const host = document.getElementById(STAGE_ID);
if (host === null) {
    throw new Error(NO_STAGE);
}
const query = new URLSearchParams(window.location.search);
if (query.has(CARD_PARAMETER) || query.has(PROFILE_PARAMETER)) {
    try {
        const target = captureTarget(query);
        await showCapture(host, target.spec, target.profile);
    } catch (error) {
        Reflect.set(window, ERROR_FLAG, messageOf(error));
        throw error;
    }
} else {
    const loaded = loadCards();
    const findings = validateCards(loaded.cards, loaded.plugins, {
        brand: loaded.brand,
        pages: loaded.pages,
        profiles: PROFILES,
        repeated: loaded.repeated,
    });
    const stopGrid = renderGrid(host, loaded.cards, loaded.pages, findings);
    import.meta.hot?.dispose(stopGrid);
}
```
