Usage rules
Usage rules enforce that code uses the right building blocks, reach for your design-system Input, not a raw <input>; call a service, not fetch. This is the one place Shapelint looks inside function bodies and JSX.
Two rule options, both taking a list of UsageBan:
disallowElements: ban JSX elements/components.disallowCalls: ban function calls.
{
name: 'ui-primitive',
files: 'components/ui/**/*.tsx',
disallowElements: [
{ name: 'input', useInstead: 'the Input component', except: ['components/ui/Input.tsx'] },
],
disallowCalls: [
{ name: 'fetch', useInstead: 'a service in @/services' },
{ name: 'axios.*', useInstead: 'a service in @/services' },
],
}The UsageBan shape
| Field | Description |
|---|---|
name | The element tag or call callee to ban. * is a wildcard segment: axios.*, use*Query. |
useInstead | The replacement, shown verbatim in the diagnostic. |
within | Only ban inside this lexical JSX ancestor (e.g. 'Form'). Omit for anywhere. |
except | File globs exempt from this ban, e.g. the primitive's own file may use the raw element. |
Element identity
- A lowercase
name(input,div) matches the raw HTML tag. - A capitalized
name(Input) matches that component by identifier.
Context-sensitivity (within)
disallowElements: [{ name: 'Input', useInstead: 'InputField', within: 'Form' }];Input is allowed everywhere except lexically inside a <Form>…</Form>.
Lexical only.
withinsees JSX ancestors in the same file. If a<Form>renders a child component that itself renders anInput, Shapelint cannot see across that component boundary, no static tool can. This is a deliberate limit, not a bug.
Self-exclusion (except)
The component that provides the primitive legitimately uses the raw element:
{ name: 'input', useInstead: 'the Input component', except: ['components/ui/Input.tsx'] }Without except, Input.tsx would flag its own <input>.
Banning backend & utility calls
disallowCalls applies across any tier of the stack to enforce logging, caching, configuration, or I/O abstractions:
// Ban direct synchronous I/O or raw environment access in domain services
{
name: 'domain-service',
files: 'domain/services/**/*.ts',
disallowCalls: [
{ name: 'fs.readFileSync', useInstead: 'the FileStorageService repository' },
{ name: 'console.log', useInstead: 'this.logger.info' },
{ name: 'process.env.*', useInstead: 'the AppConfig service' },
],
}Diagnostic codes
ARCH_DISALLOWED_ELEMENTARCH_DISALLOWED_CALL