# shared/manifests/layer.manifest.ts

> 79 lines of code and 24 definitions.

Tree: Governance tree
Language: typescript
Layer: infrastructure
Canonical: https://banes-lab.com/anatomy/governance#file-governance-shared-manifests-layer-manifest-ts
Source text: https://banes-lab.com/source/governance/shared/manifests/layer.manifest.ts.txt

Listed in [shared/manifests](https://banes-lab.com/api/source/governance/shared/manifests.md), after [shared/manifests/invariant.manifest.ts](https://banes-lab.com/source/governance/shared/manifests/invariant.manifest.ts.md) and before [shared/manifests/punctuation.manifest.ts](https://banes-lab.com/source/governance/shared/manifests/punctuation.manifest.ts.md).

## Definitions

- `relativeFromMember` (lexical_declaration, line 52, exported)
- `classifyFile` (lexical_declaration, line 77, exported)
- `prefixTier` (lexical_declaration, line 70)
- `container` (lexical_declaration, line 7)
- `concern` (lexical_declaration, line 14)
- `resolveImportPath` (lexical_declaration, line 89, exported)
- `MEMBER_PREFIX` (lexical_declaration, line 5)
- `folder` (lexical_declaration, line 15)
- `PLATFORM_PATH_PREFIXES` (lexical_declaration, line 22, exported)
- `PRODUCT_PATH_PREFIXES` (lexical_declaration, line 24, exported)
- `TYPES_PREFIX` (lexical_declaration, line 30)
- `DERIVATION_MODULES` (lexical_declaration, line 32, exported)
- `STRINGS_PREFIX` (lexical_declaration, line 42)
- `STRING_LAYERS` (lexical_declaration, line 44, exported)
- `TYPE_LAYERS` (lexical_declaration, line 46, exported)
- `normalizePath` (lexical_declaration, line 48, exported)
- `norm` (lexical_declaration, line 53, exported)
- `idx` (lexical_declaration, line 54, exported)
- `PER_FILE_OVERRIDES` (lexical_declaration, line 58)
- `overrideFor` (lexical_declaration, line 60)
- `hit` (lexical_declaration, line 62)
- `declared` (lexical_declaration, line 79, exported)
- `rel` (lexical_declaration, line 93, exported)
- `importerDir` (lexical_declaration, line 94, exported)

## Uses

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

## Used by

- [rules/eslint/closure-no-cross-subsystem-import.eslint.rule.ts](https://banes-lab.com/source/governance/rules/eslint/closure-no-cross-subsystem-import.eslint.rule.ts.md)
- [rules/eslint/closure-no-platform-product-import.eslint.rule.ts](https://banes-lab.com/source/governance/rules/eslint/closure-no-platform-product-import.eslint.rule.ts.md)
- [rules/eslint/closure-no-type-layer-drift.eslint.rule.ts](https://banes-lab.com/source/governance/rules/eslint/closure-no-type-layer-drift.eslint.rule.ts.md)

## Source

```typescript
import { GOVERNED_ROOT, collapsePath } from "../resolvers/anchor.resolver.ts";
import { folderFor, isDeclaredContainer } from "./taxonomy.manifest.ts";
import { undeclaredConcernTag, undeclaredTierContainer } from "../strings/taxonomy.strings.ts";

const MEMBER_PREFIX = `${GOVERNED_ROOT}/`;

const container = function container(name: string): string {
    if (!isDeclaredContainer(GOVERNED_ROOT, name)) {
        throw new Error(undeclaredTierContainer(name, GOVERNED_ROOT));
    }
    return name;
};

const concern = function concern(tag: string): string {
    const folder = folderFor(tag);
    if (folder === undefined) {
        throw new Error(undeclaredConcernTag(tag));
    }
    return folder;
};

export const PLATFORM_PATH_PREFIXES = [`${container("core")}/`];

export const PRODUCT_PATH_PREFIXES = [
    `${container("domain")}/`,
    `${container("presentation")}/`,
    `${container("runtime")}/`,
];

const TYPES_PREFIX = `${container("types")}/`;

export const DERIVATION_MODULES: ReadonlySet<string> = new Set([
    `${container("core")}/${concern("loader")}/definition.loader.ts`,
    `${container("core")}/${concern("converter")}/definition.converter.ts`,
    `${container("core")}/${concern("matcher")}/vocabulary.matcher.ts`,
    `${container("configuration")}/${concern("constants")}/evidence.source.constants.ts`,
    `${container("domain")}/${concern("converter")}/link.vocabulary.converter.ts`,
    `${container("domain")}/${concern("converter")}/source.link.converter.ts`,
    `${container("domain")}/${concern("converter")}/anatomy.reference.converter.ts`,
]);

const STRINGS_PREFIX = `${container("configuration")}/${concern("strings")}/`;

export const STRING_LAYERS = new Map<string, string>([[`${STRINGS_PREFIX}report.strings.ts`, "platform"]]);

export const TYPE_LAYERS = new Map<string, string>();

export const normalizePath = function normalizePath(path: string): string {
    return path.split("\\").join("/");
};

export const relativeFromMember = function relativeFromMember(filepath: string): string {
    const norm = normalizePath(filepath);
    const idx = norm.indexOf(MEMBER_PREFIX);
    return idx === -1 ? norm : norm.slice(idx + MEMBER_PREFIX.length);
};

const PER_FILE_OVERRIDES: readonly ReadonlyMap<string, string>[] = [TYPE_LAYERS, STRING_LAYERS];

const overrideFor = function overrideFor(rel: string): string | null {
    for (const declared of PER_FILE_OVERRIDES) {
        const hit = declared.get(rel);
        if (hit !== undefined) {
            return hit;
        }
    }
    return null;
};

const prefixTier = function prefixTier(rel: string): string | null {
    if (PLATFORM_PATH_PREFIXES.some((prefix) => rel.startsWith(prefix))) {
        return "platform";
    }
    return PRODUCT_PATH_PREFIXES.some((prefix) => rel.startsWith(prefix)) ? "product" : null;
};

export const classifyFile = function classifyFile(filepath: string): string | null {
    const rel = relativeFromMember(filepath);
    const declared = overrideFor(rel);
    if (declared !== null) {
        return declared;
    }
    if (rel.startsWith(TYPES_PREFIX)) {
        return null;
    }
    return rel.startsWith(STRINGS_PREFIX) ? "product" : prefixTier(rel);
};

export const resolveImportPath = function resolveImportPath(importerFile: string, importStr: string): string | null {
    if (!importStr.startsWith(".")) {
        return null;
    }
    const rel = relativeFromMember(importerFile);
    const importerDir = rel.slice(0, rel.lastIndexOf("/"));
    return collapsePath(`${importerDir}/${importStr}`);
};
```
