Skip to content

Style Rules

Core style rules enforce structural and naming conventions in chant projects. These rules apply to all projects regardless of lexicon.


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 COR001
export const bucket = new _.Bucket({
bucketEncryption: {
serverSideEncryptionConfiguration: [
{ serverSideEncryptionByDefault: { sseAlgorithm: "AES256" } },
],
},
});
// ✅ Fixed — extract each config value
export 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.


Exported declarable instances should use camelCase naming. PascalCase and UPPER_SNAKE_CASE are reserved for types and constants.

Severity: warning

// ❌ Triggers COR005
export const DataBucket = new _.Bucket({
bucketName: "my-data",
});
export const DATA_BUCKET = new _.Bucket({
bucketName: "my-data",
});
// ✅ Fixed
export const dataBucket = new _.Bucket({
bucketName: "my-data",
});

Only applies to exported variables initialized with new expressions.


Files should not contain too many resource declarations. The default limit is 8.

Severity: warning

⚠ COR009: File contains 12 Declarable instances (limit: 8) — consider splitting into separate files by concern

Fix: Split the file by concern. For example, separate networking resources from compute resources.

The limit can be configured:

chant.config.ts
export default {
lint: {
rules: {
COR009: ["warning", { max: 12 }],
},
},
};

When a namespace import already exists for a package, a separate import type from the same package is redundant.

Severity: warning

// ❌ Triggers COR012
import { isDeclarable } from "@intentius/chant";
import type { Declarable } from "@intentius/chant";
// ✅ Fixed — import the type as a named import
import { isDeclarable, type Declarable } from "@intentius/chant";
const d: Declarable = /* ... */;

This rule is auto-fixable — chant lint --fix removes the redundant import type line.


Files should not mix resource declarations with configuration/property declarations. Resources (e.g., Bucket, Function, Role) and properties (e.g., BucketEncryption, VersioningConfiguration, PublicAccessBlockConfiguration) belong in separate files.

Severity: info

// ❌ Triggers COR013 — mixes resource and configuration
export 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.


AttrRef and other intrinsic types already satisfy Value<T>, so casting with as Value<...> is redundant.

Severity: warning

// ❌ Triggers COR015
export const fn = new _.Function({
role: functionRole.arn as Value<string>,
});
// ✅ Fixed — use directly without cast
export const fn = new _.Function({
role: functionRole.arn,
});