# rules/plugins/rule.plugin.ts

> 70 lines of code and 17 definitions.

Tree: Governance tree
Language: typescript
Layer: infrastructure
Canonical: https://banes-lab.com/anatomy/governance#file-governance-rules-plugins-rule-plugin-ts
Source text: https://banes-lab.com/source/governance/rules/plugins/rule.plugin.ts.txt

Listed in [rules/plugins](https://banes-lab.com/api/source/governance/rules/plugins.md), before [rules/plugins/stylelint.plugin.ts](https://banes-lab.com/source/governance/rules/plugins/stylelint.plugin.ts.md).

## Definitions

- `isRecord` (lexical_declaration, line 9)
- `isObject` (lexical_declaration, line 54)
- `filenameOf` (lexical_declaration, line 17)
- `create` (method_definition, line 31)
- `isWorkspaceWide` (lexical_declaration, line 38)
- `mergePluginInto` (lexical_declaration, line 58)
- `isRuleModule` (lexical_declaration, line 13)
- `RuleModule` (interface_declaration, line 4)
- `declared` (lexical_declaration, line 21)
- `accessor` (lexical_declaration, line 25)
- `scopeToProject` (lexical_declaration, line 29)
- `{ meta }` (lexical_declaration, line 39)
- `{ docs }` (lexical_declaration, line 43)
- `scoped` (lexical_declaration, line 47)
- `merged` (lexical_declaration, line 62)
- `plugins` (lexical_declaration, line 70)
- `existing` (lexical_declaration, line 76)

## Uses

- [shared/resolvers/anchor.resolver.ts](https://banes-lab.com/source/governance/shared/resolvers/anchor.resolver.ts.md)

## Source

```typescript
import { LOCAL_RULES, PLUGIN_MODULES } from "../../shared/generated/rule-index.generated.ts";
import { isGovernedFile } from "../../shared/resolvers/anchor.resolver.ts";

interface RuleModule {
    meta: unknown;
    create: (context: unknown) => Record<string, unknown>;
}

const isRecord = function isRecord(value: unknown): value is Record<string, unknown> {
    return typeof value === "object" && value !== null;
};

const isRuleModule = function isRuleModule(value: unknown): value is RuleModule {
    return isRecord(value) && "meta" in value && typeof value["create"] === "function";
};

const filenameOf = function filenameOf(context: unknown): string {
    if (!isRecord(context)) {
        return "";
    }
    const declared = context["filename"];
    if (typeof declared === "string") {
        return declared;
    }
    const accessor = context["getFilename"];
    return typeof accessor === "function" ? String(accessor.call(context)) : "";
};

const scopeToProject = function scopeToProject(rule: RuleModule): RuleModule {
    return {
        create(context: unknown) {
            return isGovernedFile(filenameOf(context)) ? rule.create(context) : {};
        },
        meta: rule.meta,
    };
};

const isWorkspaceWide = function isWorkspaceWide(rule: RuleModule): boolean {
    const { meta } = rule;
    if (!isRecord(meta)) {
        return false;
    }
    const { docs } = meta;
    return isRecord(docs) && docs["workspaceWide"] === true;
};

const scoped: Record<string, RuleModule> = {};
for (const [name, rule] of Object.entries(LOCAL_RULES)) {
    if (isRuleModule(rule)) {
        scoped[name] = isWorkspaceWide(rule) ? rule : scopeToProject(rule);
    }
}

const isObject = function isObject(value: unknown): value is Record<string, unknown> {
    return value !== null && typeof value === "object" && !Array.isArray(value);
};

const mergePluginInto = function mergePluginInto(
    target: Record<string, unknown>,
    incoming: Record<string, unknown>,
): Record<string, unknown> {
    const merged: Record<string, unknown> = { ...target };
    for (const [key, value] of Object.entries(incoming)) {
        const existing = merged[key];
        merged[key] = isObject(existing) && isObject(value) ? { ...existing, ...value } : value;
    }
    return merged;
};

const plugins: Record<string, unknown> = { local: { rules: scoped } };
for (const module of PLUGIN_MODULES) {
    if (!isObject(module) || !isObject(module["plugins"])) {
        continue;
    }
    for (const [namespace, plugin] of Object.entries(module["plugins"])) {
        const existing = isObject(plugins[namespace]) ? plugins[namespace] : {};
        plugins[namespace] = isObject(plugin) ? mergePluginInto(existing, plugin) : plugin;
    }
}

export default { plugins, tool: "eslint" };
```
