Style Rules
Core style rules check structure and naming in every chant project, whatever the lexicon.
COR001: Inline Object in Constructor
Section titled “COR001: Inline Object in Constructor”Resource constructor properties must not contain inline object literals or arrays-of-objects. Each config value should be its own named, exported const.
Severity: warning
// ❌ Triggers COR001export const bucket = new _.Bucket({ bucketEncryption: { serverSideEncryptionConfiguration: [ { serverSideEncryptionByDefault: { sseAlgorithm: "AES256" } }, ], },});// ✅ Fixed — extract each config valueexport const encryptionDefault = new _.ServerSideEncryptionByDefault({ sseAlgorithm: "AES256",});
export const encryptionRule = new _.ServerSideEncryptionRule({ serverSideEncryptionByDefault: encryptionDefault,});
export const bucketEncryption = new _.BucketEncryption({ serverSideEncryptionConfiguration: [encryptionRule],});
export const bucket = new _.Bucket({ bucketEncryption: bucketEncryption,});Simple string, number, and boolean properties are allowed inline. Only nested object literals and arrays containing objects are flagged.
The rule looks only at resource constructors. A property-kind declarable is one a lexicon builds with createProperty and lists in its plugin’s propertyClassNames(). It is already a nested value inside the resource that holds it, so the objects passed to it are not flagged. Grafana declares its panel classes this way, so a panel can carry its fieldConfig and options inline.
// OK: TimeSeriesPanel is property-kindexport const overview = new Dashboard({ title: "Overview", panels: [ new TimeSeriesPanel({ title: "Latency", fieldConfig: { defaults: { unit: "ms" } } }), ],});A lexicon that does not implement propertyClassNames() gets the rule on every constructor, as before.
COR005: Naming Convention
Section titled “COR005: Naming Convention”Exported declarable instances should use camelCase naming. PascalCase and UPPER_SNAKE_CASE are reserved for types and constants.
Severity: warning
// ❌ Triggers COR005export const DataBucket = new _.Bucket({ bucketName: "my-data",});
export const DATA_BUCKET = new _.Bucket({ bucketName: "my-data",});// ✅ Fixedexport const dataBucket = new _.Bucket({ bucketName: "my-data",});Only applies to exported variables initialized with new expressions.
COR009: File Declarable Limit
Section titled “COR009: File Declarable Limit”A file may hold up to 8 resource declarations by default.
Only resources count. The classes a lexicon lists in its plugin’s propertyClassNames() are property-kind and are left out. A Grafana dashboard file with twenty panels inside one dashboard counts as one declarable. A lexicon that does not implement propertyClassNames() has every declarable counted, as before.
Severity: warning
⚠ COR009: File contains 12 Declarable instances (limit: 8) — consider splitting into separate files by concernFix: Split the file by concern. For example, separate networking resources from compute resources.
Configure the limit:
export default { lint: { rules: { COR009: ["warning", { max: 12 }], }, },};COR012: Redundant Type Import
Section titled “COR012: Redundant Type Import”When a namespace import already exists for a package, a separate import type from the same package is redundant.
Severity: warning
// ❌ Triggers COR012import { isDeclarable } from "@intentius/chant";import type { Declarable } from "@intentius/chant";// ✅ Fixed — import the type as a named importimport { isDeclarable, type Declarable } from "@intentius/chant";
const d: Declarable = /* ... */;chant lint --fix removes the redundant import type line.
COR013: Single-Concern File
Section titled “COR013: Single-Concern File”Keep resources (e.g., Bucket, Function, Role) and properties (e.g., BucketEncryption, VersioningConfiguration, PublicAccessBlockConfiguration) in separate files.
Severity: info
// ❌ Triggers COR013 — mixes resource and configurationexport const encryptionDefault = new _.ServerSideEncryptionByDefault({ sseAlgorithm: "AES256",});
export const bucket = new _.Bucket({ bucketEncryption: _.bucketEncryption,});Fix: Move configuration declarations to a defaults.ts file and resources to their own files.
COR015: Redundant Value Cast
Section titled “COR015: Redundant Value Cast”AttrRef and other intrinsic types already satisfy Value<T>, so casting with as Value<...> is redundant.
Severity: warning
// ❌ Triggers COR015export const fn = new _.Function({ role: functionRole.arn as Value<string>,});// ✅ Fixed — use directly without castexport const fn = new _.Function({ role: functionRole.arn,});