internal-import-from-outside
a file inside an `internal/` folder imported from outside the folder that holds it
Deterministic checkoff by defaultbasecode
The argument
Private Files Live in internal/
A folder's private files sit in its internal/ folder, and only files inside that folder import them. Everything outside internal/ is the folder's public API.
src/ingestion/
├─ ingestRecords.ts # public — anyone may import it
├─ ingestRecords.unit.test.ts
└─ internal/
├─ parseRow.ts # private to src/ingestion/
└─ parseRow.unit.test.ts
- Inside the folder:
src/ingestion/ingestRecords.tsimports./internal/parseRow— correct. So does any test undersrc/ingestion/. - Outside it:
src/reporting/buildReport.tsimporting../ingestion/internal/parseRowis a finding. Import the public file that uses it, or — if the file is genuinely shared — move it out ofinternal/. - The path is the whole statement. Privacy is where the file sits, so a reader sees it in the import line itself, with no list in another file to consult.
- Nested folders nest the rule.
src/ingestion/parser/internal/tokenize.tsis private tosrc/ingestion/parser/. internal/marks privacy, not a new kind of place. What goes inside it follows the same placement rules as any other folder — shared helpers in acommon/under it, a graduated concept in its own folder.
A repo opts into this rule by naming it in standards-checks; until it does, nothing here applies to it.
The proof
fail
import { parseRow } from './internal/parseRow';
export const ingestRecords = (): number => parseRow();
pass
import { parseRow } from './internal/parseRow';
export const ingestRecords = (): number => parseRow();
Turn it on
Both lines go in your lightsout.config.json.
"standards-checks": { "internal-import-from-outside": "blocking" }"standards-checks": { "internal-import-from-outside": "advisory" }