# core/adapters/stage.adapter.ts

> 62 lines of code and 13 definitions.

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

Listed in [core/adapters](https://banes-lab.com/api/source/social-share/core/adapters.md), after [core/adapters/image.adapter.ts](https://banes-lab.com/source/social-share/core/adapters/image.adapter.ts.md).

## Definitions

- `locationOf` (lexical_declaration, line 20)
- `release` (lexical_declaration, line 33, exported)
- `openStage` (lexical_declaration, line 32, exported)
- `listenedPort` (lexical_declaration, line 24)
- `LoaderModule` (interface_declaration, line 10)
- `LOOPBACK` (lexical_declaration, line 14)
- `SECURE_SCHEME` (lexical_declaration, line 15)
- `PORT_MARK` (lexical_declaration, line 16)
- `PATH_END` (lexical_declaration, line 17)
- `SYSTEM_ASSIGNED` (lexical_declaration, line 18)
- `server` (lexical_declaration, line 34, exported)
- `runner` (lexical_declaration, line 52, exported)
- `address` (lexical_declaration, line 53, exported)

## Contained in

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

## Uses

- [configuration/strings/card.strings.ts](https://banes-lab.com/source/social-share/configuration/strings/card.strings.ts.md)

## Linked from

- [configuration/strings](https://banes-lab.com/anatomy/social-share/folder-social-share-configuration-strings.md)
- [core/adapters](https://banes-lab.com/anatomy/social-share/folder-social-share-core-adapters.md)

## Source

```typescript
import type { LoadedCards, StageServer } from "#types/stage.types";
import { type ViteDevServer, createServer, createServerModuleRunner } from "vite";
import { STAGE_MODE } from "#configuration/constants/card.constants";
import { devCertificate } from "@banes-lab/build-scripts/core/factories/certificate.factory.ts";
import { fileURLToPath } from "node:url";
import { holdCaptureLock } from "#core/persistence/export.persistence";
import { releaseServer } from "@banes-lab/build-scripts/core/factories/server.factory.ts";
import { stageUnaddressed } from "#configuration/strings/card.strings";

interface LoaderModule {
    readonly loadCards: () => LoadedCards;
}

const LOOPBACK = "127.0.0.1";
const SECURE_SCHEME = "https://";
const PORT_MARK = ":";
const PATH_END = "/";
const SYSTEM_ASSIGNED = 0;

const locationOf = function locationOf(specifier: string): string {
    return fileURLToPath(import.meta.resolve(specifier));
};

const listenedPort = function listenedPort(server: ViteDevServer): number {
    const address = server.httpServer?.address();
    if (address === null || address === undefined || typeof address === "string") {
        throw new Error(stageUnaddressed(String(address)));
    }
    return address.port;
};

export const openStage = async function openStage(listen: boolean): Promise<StageServer> {
    const release = listen ? holdCaptureLock() : (): void => undefined;
    const server = await createServer({
        appType: listen ? "spa" : "custom",
        configFile: locationOf("@banes-lab/social-share/vite.config.ts"),
        logLevel: "error",
        mode: STAGE_MODE,
        server: listen
            ? {
                  hmr: false,
                  host: LOOPBACK,
                  https: await devCertificate(),
                  port: SYSTEM_ASSIGNED,
                  strictPort: true,
              }
            : { hmr: false, middlewareMode: true, ws: false },
    });
    if (listen) {
        await server.listen();
    }
    const runner = createServerModuleRunner(server.environments.ssr);
    const address = listen ? PORT_MARK + String(listenedPort(server)) : "";
    return {
        cards: async (): Promise<LoadedCards> =>
            (await runner.import<LoaderModule>(locationOf("#core/loaders/card.loader"))).loadCards(),
        close: async (): Promise<void> => {
            try {
                await runner.close();
                await releaseServer(server);
            } finally {
                release();
            }
        },
        url: SECURE_SCHEME + LOOPBACK + address + PATH_END,
    };
};
```
