package-shape
Every workspace is named
<scope>/<dir>; library packages expose a barrel and point their build fields at the built output.
Runs under: @noctcore/harness lint-meta, not ESLint · Factory: createPackageShapeRule from @noctcore/lint-meta-rules · Category: config · Fails CI by default: yes
A monorepo stays navigable when a package’s identity is mechanical: its npm name matches its folder,
and a library’s public surface is a single barrel whose published entrypoints resolve to built output
rather than raw source. This makes “where does @scope/foo live?” and “what does it export?”
answerable without reading the file.
What it flags
Section titled “What it flags”For each package.json matched by libraryGlobs (full checks) or appGlobs (name check only):
- name — must equal
<scope>/<dir-basename>(or anexternalNamesoverride). - barrel (library only) — the package must expose the configured
barrelPath. - build fields (library only) — each of
distFieldspresent as a string must containdistMarker, andexportsmust reference it. - invalid JSON — reported as a violation.
What it does not flag
Section titled “What it does not flag”- Barrel and build-field problems in app/surface packages: they are deployable entrypoints (vite/tauri/bun), so only the name check applies to them.
- A package whose directory has an
externalNamesentry and whose name equals it. - A missing
distFieldsentry or a missingexports: only fields that are present are checked, andexportspasses when any of its targets containsdistMarker. package.jsonfiles outsidelibraryGlobsandappGlobs.
Options
Section titled “Options”createPackageShapeRule(options?: PackageShapeOptions): IMetaRule| Option | Type | Default | Meaning |
|---|---|---|---|
scope |
string |
'@nightcore' |
npm scope every workspace is named under. |
libraryGlobs |
string[] |
['packages/*/package.json'] |
Library packages (full checks). |
appGlobs |
string[] |
['apps/*/package.json'] |
App/surface packages (name check only). |
externalNames |
Record<string,string> |
{} |
Directory → exact name overrides for intentionally off-scope packages. |
barrelPath |
string |
'src/index.ts' |
Barrel each library must expose, relative to its dir. |
distMarker |
string |
'dist/' |
Substring the build-output fields must contain. |
distFields |
string[] |
['main','module','types'] |
package.json string fields that must point at built output. |
ciCritical |
boolean |
true |
Whether a violation fails CI. |
When not to use it
Section titled “When not to use it”If your packages are not scope-named after their folders, or libraries publish raw source (no build step), tune or disable the relevant checks via options.