# core/plugins/syntax.event.plugin.ts

> 47 lines of code and 13 definitions.

Tree: GovLab Docs
Language: typescript
Layer: infrastructure
Canonical: https://banes-lab.com/anatomy/docs#file-docs-core-plugins-syntax-event-plugin-ts
Source text: https://banes-lab.com/source/docs/core/plugins/syntax.event.plugin.ts.txt

Listed in [core/plugins](https://banes-lab.com/api/source/docs/core/plugins.md), after [core/plugins/syntax.branch.plugin.ts](https://banes-lab.com/source/docs/core/plugins/syntax.branch.plugin.ts.md) and before [core/plugins/syntax.failure.plugin.ts](https://banes-lab.com/source/docs/core/plugins/syntax.failure.plugin.ts.md).

## Definitions

- `ownerName` (lexical_declaration, line 9)
- `isHookCall` (lexical_declaration, line 23)
- `classify` (method_definition, line 36, exported)
- `calleeParts` (lexical_declaration, line 16)
- `LISTENER_METHOD` (lexical_declaration, line 5)
- `SUBSCRIBE_METHODS` (lexical_declaration, line 6)
- `EVENT_OWNERS` (lexical_declaration, line 7)
- `eventName` (lexical_declaration, line 30)
- `[first]` (lexical_declaration, line 31)
- `recognizer` (lexical_declaration, line 35, exported)
- `parts` (lexical_declaration, line 40, exported)
- `event` (lexical_declaration, line 44, exported)
- `id` (lexical_declaration, line 45, exported)

## Contained in

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

## Uses

- [configuration/strings/graph.strings.ts](https://banes-lab.com/source/docs/configuration/strings/graph.strings.ts.md)

## Linked from

- [configuration/strings](https://banes-lab.com/anatomy/docs/folder-docs-configuration-strings.md)
- [core/plugins](https://banes-lab.com/anatomy/docs/folder-docs-core-plugins.md)

## Source

```typescript
import type { CalleeParts, Recognizer } from "#types/code.types";
import { hookLabel } from "#configuration/strings/graph.strings";
import ts from "typescript";

const LISTENER_METHOD = "addEventListener";
const SUBSCRIBE_METHODS: ReadonlySet<string> = new Set(["add", "on"]);
const EVENT_OWNERS: readonly string[] = ["event", "manager", "bus"];

const ownerName = function ownerName(target: ts.Expression): string {
    if (ts.isIdentifier(target)) {
        return target.text;
    }
    return ts.isPropertyAccessExpression(target) ? target.name.text : "";
};

const calleeParts = function calleeParts(node: ts.CallExpression): CalleeParts | null {
    if (!ts.isPropertyAccessExpression(node.expression)) {
        return null;
    }
    return { method: node.expression.name.text, owner: ownerName(node.expression.expression).toLowerCase() };
};

const isHookCall = function isHookCall(parts: CalleeParts): boolean {
    if (parts.method === LISTENER_METHOD) {
        return true;
    }
    return SUBSCRIBE_METHODS.has(parts.method) && EVENT_OWNERS.some((owner) => parts.owner.includes(owner));
};

const eventName = function eventName(node: ts.CallExpression, method: string): string {
    const [first] = node.arguments;
    return first && ts.isStringLiteralLike(first) ? first.text : method;
};

export const recognizer: Recognizer = {
    classify(node, context) {
        if (!ts.isCallExpression(node)) {
            return null;
        }
        const parts = calleeParts(node);
        if (parts === null || !isHookCall(parts)) {
            return null;
        }
        const event = eventName(node, parts.method);
        const id = context.mkNodeId(node);
        return {
            edges: [{ from: context.currentId, kind: "hook-register", label: event, to: id }],
            nodes: [{ id, kind: "hook", label: hookLabel(event), source: context.sourceOf(node) }],
        };
    },
    emits: { edges: ["hook-register"], nodes: ["hook"] },
    name: "event-hook",
};
```
