# core/loaders/manifest.loader.ts

> 44 lines of code and 13 definitions.

Tree: Code Parse
Language: typescript
Layer: infrastructure
Canonical: https://banes-lab.com/anatomy/code-parse#file-code-parse-core-loaders-manifest-loader-ts
Source text: https://banes-lab.com/source/code-parse/core/loaders/manifest.loader.ts.txt

Listed in [core/loaders](https://banes-lab.com/api/source/code-parse/core/loaders.md), after [core/loaders/grammar.loader.ts](https://banes-lab.com/source/code-parse/core/loaders/grammar.loader.ts.md) and before [core/loaders/source.loader.ts](https://banes-lab.com/source/code-parse/core/loaders/source.loader.ts.md).

## Definitions

- `asStringArray` (lexical_declaration, line 14)
- `readGrammarMeta` (lexical_declaration, line 41, exported)
- `fileTypesForSource` (lexical_declaration, line 47, exported)
- `configEntries` (lexical_declaration, line 22)
- `packageFileTypes` (lexical_declaration, line 34)
- `readJson` (lexical_declaration, line 18)
- `grammars` (lexical_declaration, line 24)
- `parsed` (lexical_declaration, line 35)
- `meta` (lexical_declaration, line 36)
- `list` (lexical_declaration, line 37)
- `entries` (lexical_declaration, line 42, exported)
- `pool` (lexical_declaration, line 43, exported)
- `matched` (lexical_declaration, line 48, exported)

## Contained in

- [core/loaders](https://banes-lab.com/anatomy/code-parse/folder-code-parse-core-loaders.md)

## Used by

- [core/coordinators/grammar.coordinator.ts](https://banes-lab.com/source/code-parse/core/coordinators/grammar.coordinator.ts.md)

## Linked from

- [core/coordinators](https://banes-lab.com/anatomy/code-parse/folder-code-parse-core-coordinators.md)
- [core/loaders](https://banes-lab.com/anatomy/code-parse/folder-code-parse-core-loaders.md)

## Source

```typescript
import {
    FILE_TYPES_KEY,
    GRAMMARS_KEY,
    GRAMMAR_CONFIG_FILE,
    NAME_KEY,
    PACKAGE_GRAMMAR_KEY,
    PACKAGE_MANIFEST_FILE,
} from "#configuration/constants/grammar.constants";
import type { FileTypeEntry, GrammarMeta, GrammarSource } from "#types/grammar.types";
import { existsSync, readFileSync } from "node:fs";
import { isRecord } from "#core/predicates/record.predicate";
import { join } from "node:path";

const asStringArray = function asStringArray(value: unknown): string[] {
    return Array.isArray(value) ? value.filter((item): item is string => typeof item === "string") : [];
};

const readJson = function readJson(file: string): unknown {
    return existsSync(file) ? JSON.parse(readFileSync(file, "utf8")) : null;
};

const configEntries = function configEntries(packageRoot: string): FileTypeEntry[] {
    const parsed = readJson(join(packageRoot, GRAMMAR_CONFIG_FILE));
    const grammars = isRecord(parsed) && Array.isArray(parsed[GRAMMARS_KEY]) ? parsed[GRAMMARS_KEY] : [];
    return grammars
        .filter(isRecord)
        .map((grammar) => ({
            fileTypes: asStringArray(grammar[FILE_TYPES_KEY]),
            name: typeof grammar[NAME_KEY] === "string" ? grammar[NAME_KEY] : "",
        }))
        .filter((entry) => entry.name.length > 0);
};

const packageFileTypes = function packageFileTypes(packageRoot: string): string[] {
    const parsed = readJson(join(packageRoot, PACKAGE_MANIFEST_FILE));
    const meta = isRecord(parsed) ? parsed[PACKAGE_GRAMMAR_KEY] : null;
    const list: unknown[] = Array.isArray(meta) ? meta : [];
    return list.filter(isRecord).flatMap((entry) => asStringArray(entry[FILE_TYPES_KEY]));
};

export const readGrammarMeta = function readGrammarMeta(packageRoot: string): GrammarMeta {
    const entries = configEntries(packageRoot);
    const pool = [...new Set([...entries.flatMap((entry) => entry.fileTypes), ...packageFileTypes(packageRoot)])];
    return { entries, pool };
};

export const fileTypesForSource = function fileTypesForSource(source: GrammarSource, meta: GrammarMeta): string[] {
    const matched = meta.entries.find((entry) => entry.name === source.lang);
    return matched && matched.fileTypes.length > 0 ? matched.fileTypes : meta.pool;
};
```
