# codemods/selectors/program.selector.ts

> 46 lines of code and 20 definitions.

Tree: Governance tree
Language: typescript
Layer: application
Canonical: https://banes-lab.com/anatomy/governance#file-governance-codemods-selectors-program-selector-ts
Source text: https://banes-lab.com/source/governance/codemods/selectors/program.selector.ts.txt

Listed in [codemods/selectors](https://banes-lab.com/api/source/governance/codemods/selectors.md), after [codemods/selectors/heritage.selector.ts](https://banes-lab.com/source/governance/codemods/selectors/heritage.selector.ts.md).

## Definitions

- `lineOf` (lexical_declaration, line 55, exported)
- `relPath` (lexical_declaration, line 30, exported)
- `repoSourceFiles` (lexical_declaration, line 49, exported)
- `inRepo` (lexical_declaration, line 34, exported)
- `toPosix` (lexical_declaration, line 26, exported)
- `programFor` (lexical_declaration, line 38, exported)
- `REPO_ROOT` (lexical_declaration, line 6)
- `NODE_MODULES` (lexical_declaration, line 7)
- `ARGV_START` (lexical_declaration, line 8)
- `TSCONFIG_FLAG` (lexical_declaration, line 9)
- `TSCONFIG` (lexical_declaration, line 10)
- `ALL_TSCONFIGS` (lexical_declaration, line 12)
- `requestedTsconfigs` (lexical_declaration, line 16)
- `flagIndex` (lexical_declaration, line 17)
- `value` (lexical_declaration, line 18)
- `REQUESTED` (lexical_declaration, line 22)
- `CODEMOD_TSCONFIGS` (lexical_declaration, line 24, exported)
- `absolute` (lexical_declaration, line 39, exported)
- `configFile` (lexical_declaration, line 40, exported)
- `parsed` (lexical_declaration, line 41, exported)

## Uses

- [rules/eslint/closure-no-cross-member-relative.eslint.rule.ts](https://banes-lab.com/source/governance/rules/eslint/closure-no-cross-member-relative.eslint.rule.ts.md)

## Used by

- [codemods/analyzers/binding.analyzer.ts](https://banes-lab.com/source/governance/codemods/analyzers/binding.analyzer.ts.md)
- [codemods/analyzers/code-point.analyzer.ts](https://banes-lab.com/source/governance/codemods/analyzers/code-point.analyzer.ts.md)
- [codemods/analyzers/field.analyzer.ts](https://banes-lab.com/source/governance/codemods/analyzers/field.analyzer.ts.md)
- [codemods/analyzers/field.vocabulary.analyzer.ts](https://banes-lab.com/source/governance/codemods/analyzers/field.vocabulary.analyzer.ts.md)
- [codemods/analyzers/identifier.analyzer.ts](https://banes-lab.com/source/governance/codemods/analyzers/identifier.analyzer.ts.md)
- [codemods/analyzers/increment.analyzer.ts](https://banes-lab.com/source/governance/codemods/analyzers/increment.analyzer.ts.md)
- [codemods/analyzers/location.analyzer.ts](https://banes-lab.com/source/governance/codemods/analyzers/location.analyzer.ts.md)
- [codemods/analyzers/specifier.analyzer.ts](https://banes-lab.com/source/governance/codemods/analyzers/specifier.analyzer.ts.md)
- [codemods/analyzers/specifier.target.analyzer.ts](https://banes-lab.com/source/governance/codemods/analyzers/specifier.target.analyzer.ts.md)
- [codemods/analyzers/vocabulary.analyzer.ts](https://banes-lab.com/source/governance/codemods/analyzers/vocabulary.analyzer.ts.md)
- [codemods/analyzers/word.analyzer.ts](https://banes-lab.com/source/governance/codemods/analyzers/word.analyzer.ts.md)
- [codemods/entrypoints/code-point.entrypoint.ts](https://banes-lab.com/source/governance/codemods/entrypoints/code-point.entrypoint.ts.md)
- [codemods/entrypoints/identifier.entrypoint.ts](https://banes-lab.com/source/governance/codemods/entrypoints/identifier.entrypoint.ts.md)
- [codemods/entrypoints/increment.entrypoint.ts](https://banes-lab.com/source/governance/codemods/entrypoints/increment.entrypoint.ts.md)

## Source

```typescript
import { dirname, relative, resolve, sep } from "node:path";
import { MEMBER_ROOTS } from "../../shared/registries/location.registry.ts";
import { existsSync } from "node:fs";
import ts from "typescript";

const REPO_ROOT = process.cwd().split(sep).join("/");
const NODE_MODULES = "/node_modules/";
const ARGV_START = 2;
const TSCONFIG_FLAG = "--tsconfig";
const TSCONFIG = "tsconfig.json";

const ALL_TSCONFIGS: readonly string[] = MEMBER_ROOTS.map((member) => `${member}/${TSCONFIG}`).filter((file) =>
    existsSync(resolve(process.cwd(), file)),
);

const requestedTsconfigs = function requestedTsconfigs(argv: readonly string[]): string[] {
    const flagIndex = argv.indexOf(TSCONFIG_FLAG);
    const value = flagIndex === -1 ? "" : (argv[flagIndex + 1] ?? "");
    return value.split(",").filter((entry) => entry.length > 0);
};

const REQUESTED = requestedTsconfigs(process.argv.slice(ARGV_START));

export const CODEMOD_TSCONFIGS: readonly string[] = REQUESTED.length > 0 ? REQUESTED : ALL_TSCONFIGS;

export const toPosix = function toPosix(value: string): string {
    return value.split(sep).join("/");
};

export const relPath = function relPath(fileName: string): string {
    return toPosix(relative(process.cwd(), fileName));
};

export const inRepo = function inRepo(fileName: string): boolean {
    return toPosix(fileName).startsWith(REPO_ROOT) && !toPosix(fileName).includes(NODE_MODULES);
};

export const programFor = function programFor(tsconfigPath: string): ts.Program {
    const absolute = resolve(process.cwd(), tsconfigPath);
    const configFile = ts.readConfigFile(absolute, (file) => ts.sys.readFile(file));
    const parsed = ts.parseJsonConfigFileContent(configFile.config, ts.sys, dirname(absolute));
    return ts.createProgram({
        host: ts.createCompilerHost(parsed.options),
        options: parsed.options,
        rootNames: parsed.fileNames,
    });
};

export const repoSourceFiles = function repoSourceFiles(program: ts.Program): ts.SourceFile[] {
    return program
        .getSourceFiles()
        .filter((sourceFile) => !sourceFile.isDeclarationFile && inRepo(sourceFile.fileName));
};

export const lineOf = function lineOf(sourceFile: ts.SourceFile, node: ts.Node): number {
    return sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile)).line + 1;
};
```
