# tools/core/runners/member.runner.ts

> 51 lines of code and 13 definitions.

Tree: Coordination tree
Language: typescript
Canonical: https://banes-lab.com/anatomy/coordination#file-coordination-tools-core-runners-member-runner-ts
Source text: https://banes-lab.com/assets/sources/source.0746aa8323892fb53dc07ff37ccd1a997755d55643d4cf9b9769db33c71c2804.generated.txt

## Definitions

- `regionAt` (lexical_declaration, line 30)
- `runMember` (lexical_declaration, line 40, exported)
- `MemberRequest` (interface_declaration, line 12, exported)
- `MemberOutcome` (interface_declaration, line 19, exported)
- `MEMBER_MARKER` (lexical_declaration, line 24)
- `REGION_LEAD` (lexical_declaration, line 26)
- `REGION_WORD` (lexical_declaration, line 28)
- `index` (lexical_declaration, line 31)
- `line` (lexical_declaration, line 32)
- `before` (lexical_declaration, line 45, exported)
- `lines` (lexical_declaration, line 46, exported)
- `written` (lexical_declaration, line 56, exported)
- `witness` (lexical_declaration, line 58, exported)

## Uses

- [tools/core/strings/member.strings.ts](https://banes-lab.com/source/coordination/tools/core/strings/member.strings.ts.md)

## Source

```typescript
import { existsSync, readFileSync, writeFileSync } from "node:fs";

import {
    headingTaken,
    memberAdded,
    memberContended,
    regionMissing,
    surfaceMissing,
} from "../strings/member.strings.ts";
import { appendSection } from "../formatters/text.formatter.ts";

export interface MemberRequest {
    readonly target: string;
    readonly absolute: string;
    readonly heading: string;
    readonly body: string;
}

export interface MemberOutcome {
    readonly message: string;
    readonly code: number;
}

const MEMBER_MARKER = "## ";

const REGION_LEAD = "═";

const REGION_WORD = "ROWS";

const regionAt = function regionAt(lines: readonly string[]): number {
    for (let index = 0; index < lines.length; index += 1) {
        const line = lines[index] ?? "";
        if (line.startsWith(REGION_LEAD) && line.includes(REGION_WORD)) {
            return index;
        }
    }
    return -1;
};

export const runMember = function runMember(request: MemberRequest): MemberOutcome {
    if (!existsSync(request.absolute)) {
        return { code: 2, message: surfaceMissing(request.target) };
    }

    const before = readFileSync(request.absolute, "utf8");
    const lines = before.split("\n");

    if (regionAt(lines) === -1) {
        return { code: 2, message: regionMissing(request.target) };
    }

    if (before.includes(`${MEMBER_MARKER}${request.heading}`)) {
        return { code: 2, message: headingTaken(request.heading, request.target) };
    }

    const written = appendSection(before, `${MEMBER_MARKER}${request.heading}`, request.body);

    const witness = readFileSync(request.absolute, "utf8");
    if (witness !== before) {
        return { code: 2, message: memberContended(request.target) };
    }

    writeFileSync(request.absolute, written, "utf8");

    return { code: 0, message: memberAdded(request.heading, request.target) };
};
```
