ccfb08f4d5
Follow-up to #20, which was merged before this landed. bot-agents has no `package.json` `imports` aliases (`src/` is flat and everything imports relatively), so no code changes. This records the new rule in the docs: - `.agents/memory/imports-aliases-barrels.md`: aliases may target only a direct subfolder of `src/` (its `index.ts` or a `#x/*` pattern); nothing outside `src/`, not `src/` itself, not deeper folders; such code imports relatively. - `.agents/memory/tests-layout-vitest.md`: `tests/` reach the public entry through a relative import, not a `#plugin` alias. - `.agents/skills/migrate-deno-repo/SKILL.md` and `AGENTS.md`: same rule. `vp check`, `vp test`, and `damem doctor` pass. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Reviewed-on: #21 Reviewed-by: bot <noreply@capsulizers.com> Co-authored-by: Danny Kim <temeddix@gmail.com> Co-committed-by: Danny Kim <temeddix@gmail.com>
105 lines
5.0 KiB
Markdown
105 lines
5.0 KiB
Markdown
---
|
|
description: An alias owns its target (folder index.ts = folder and below, any other file = that file); no overlap; outside an area only the exact alias reaches it; ../ is banned in every file; locally, aliases target only direct src/ subfolders
|
|
---
|
|
|
|
## `#` aliases own their targets
|
|
|
|
Shared code is imported through Node subpath imports declared in
|
|
`package.json` `imports`. Node, TypeScript, Vite, Vite+'s config bundler, and
|
|
Oxlint's plugin loader all resolve them natively, so `.ts` source runs
|
|
unbuilt. `vp pack` inlines them, so they never reach package consumers.
|
|
|
|
One rule for every file, never tied to folder or file names (user rule
|
|
2026-10-17; it replaces the earlier "aliases only point at direct `src/`
|
|
subfolders" rule as the general rule, and the "import-structure plugin
|
|
checks only aliased folders" scope; this repo keeps the stricter rule as a
|
|
local convention, see the last section):
|
|
|
|
- **An alias may point anywhere** and owns its target. An alias to a
|
|
folder's `index.ts` owns that folder and everything below it; an alias to
|
|
any other file owns only that file.
|
|
- **No overlap.** No file may be owned by 2 aliases: no alias inside another
|
|
alias's area, and no 2 aliases with the same target. The import-structure
|
|
plugin's `enforce-layer-order` reports it once at the top of every file 2
|
|
aliases claim. Fix by merging the aliases or moving files apart.
|
|
- **Outside an area, only the exact alias reaches it.** A deeper alias
|
|
specifier (`#a/one.ts`, `no-barrel-bypass`) and a relative path into the
|
|
area (`./a/one.ts`, `no-relative-bypass`; `./b/f.ts` to a file alias,
|
|
`prefer-alias-import`, fixed to the alias) are bypasses.
|
|
- **Inside an area, relative imports of siblings and subfolders are free.**
|
|
- **A `../` import is banned in every file**, owned or not (`no-parent-import`).
|
|
Runtime file URLs (`new URL("../prompt.md", import.meta.url)`) are not
|
|
imports and are allowed.
|
|
Anything above a file needs an alias.
|
|
- **Files no alias owns** need no `index.ts` and no alias, and import `./`
|
|
siblings and subfolders freely.
|
|
- Unchanged: no `/*` subpath patterns, the key order of `imports` is the
|
|
layer order `enforce-layer-order` checks (add a new alias at the right
|
|
layer), and entry files are `index.ts` only.
|
|
|
|
```jsonc
|
|
"imports": {
|
|
"#a": "./a/index.ts", // owns a/**
|
|
"#f": "./b/f.ts", // owns only b/f.ts
|
|
"#a-sub": "./a/sub/index.ts", // no: inside #a
|
|
"#a2": "./a/index.ts" // no: same target as #a
|
|
}
|
|
```
|
|
|
|
```ts
|
|
// in main.ts, which no alias owns
|
|
import { a } from "#a"; // yes
|
|
import { one } from "#a/one.ts"; // no: deeper alias specifier
|
|
import { one } from "./a/one.ts"; // no: relative path into #a
|
|
import { f } from "#f"; // yes
|
|
import { f } from "./b/f.ts"; // no: relative path to a file alias
|
|
import { g } from "./b/g.ts"; // yes: unowned
|
|
// in a/one.ts, owned by #a
|
|
import { two } from "./two.ts"; // yes: sibling
|
|
import { deep } from "./sub/deep.ts"; // yes: subfolder of the same area
|
|
import { x } from "../x.ts"; // no: no ../ anywhere
|
|
```
|
|
|
|
- Aliases point at `.ts` files only. There is no `#package` alias
|
|
([[ts-only-files-and-imports]]).
|
|
- Lint `jsPlugins` entries in `vite.config.ts` stay path strings, even when
|
|
the file has an alias.
|
|
- Keep test-only helpers in their own alias (e.g. `#testing`) so they never
|
|
land in a bundle.
|
|
|
|
## Barrels
|
|
|
|
- An area used from outside exposes its API through its alias target, and
|
|
callers import the alias (`#ui`), not files inside it.
|
|
- Barrels are also the standard fix for `import/max-dependencies`: one barrel
|
|
import replaces many direct ones ([[lint-overrides-policy]]).
|
|
- `import/no-cycle` is on; a barrel must not create a cycle.
|
|
|
|
Relative imports are written with the `.ts` extension.
|
|
|
|
## `scripts/` is flat (user rule, 2026-10-16)
|
|
|
|
- `scripts/` has no subfolders and no `index.ts`.
|
|
- Each tool is one file, `scripts/<name>.ts`, imported directly by file:
|
|
`import projectLint from "./scripts/project-lint.ts";` in
|
|
`vite.config.ts`. No alias owns `scripts/`, so these `./` imports are free.
|
|
- Code in a former `scripts/<tool>/` folder is merged or renamed into flat
|
|
`scripts/<name>.ts` files. Non-TS assets (HTML, images, fixtures) move to
|
|
where they belong (next to the tool's output, `.agents/`, or a gitignored
|
|
scratch dir). A subfolder that is really an app moves under an alias.
|
|
|
|
## Local convention: aliases target direct `src/` subfolders
|
|
|
|
This is a convention of this repo only, stricter than the general rule above
|
|
(which the published import-structure plugin checks and which allows more).
|
|
It is not a plugin rule.
|
|
|
|
- Every `package.json` `imports` alias points only at the `index.ts` of a
|
|
direct subfolder of `src/`, e.g. `"#helpers": "./src/helpers/index.ts"`.
|
|
No alias to a single file, a deeper folder, or anything outside `src/`.
|
|
Here the one alias is `"#testing": "./src/testing/index.ts"`.
|
|
- Code outside `src/` (`scripts/`, `tests/`, `vite.config.ts`) gets no alias
|
|
of its own and imports its own files by `./` relative paths. It reaches
|
|
`src/` only through the aliases, since `../` is banned.
|
|
- No lint rule checks this; check `imports` by hand when adding an alias.
|