Skip to content

Cross-File References

Resources often depend on each other — a policy needs a storage resource’s ARN, a function needs a table’s name. chant uses standard TypeScript imports for cross-file references.

Import a resource from another file and access its attributes:

src/cross-ref-storage.ts
import { Bucket, Sub, AWS, Ref } from "@intentius/chant-lexicon-aws";
import { environment } from "./parameters";
export const dataBucket = new Bucket({
BucketName: Sub`${AWS.StackName}-${Ref(environment)}-data`,
PublicAccessBlockConfiguration: {
BlockPublicAcls: true,
BlockPublicPolicy: true,
IgnorePublicAcls: true,
RestrictPublicBuckets: true,
},
});
src/cross-ref-policy.ts
import { Role, ManagedPolicy } from "@intentius/chant-lexicon-aws";
import { dataBucket } from "./cross-ref-storage";
export const accessRole = new Role({
AssumeRolePolicyDocument: {
Version: "2012-10-17",
Statement: [{
Effect: "Allow",
Principal: { Service: "lambda.amazonaws.com" },
Action: "sts:AssumeRole",
}],
},
});
export const readPolicy = new ManagedPolicy({
PolicyDocument: {
Statement: [{
Effect: "Allow",
Action: ["s3:GetObject"],
Resource: dataBucket.Arn,
}],
},
Roles: [accessRole],
});

dataBucket.arn resolves to a symbolic cross-resource reference in the evaluated output. The evaluator traces the import back to the source file, identifies the resource type, and resolves the attribute through the lexicon’s attribute registry.

Cross-file references are resolved at build time, not at runtime. This means:

  • References are resolved statically — the evaluator follows imports to build the resource graph
  • References to nonexistent resources produce a build error
  • Circular dependencies between resources are detected and reported
PatternExample
Import a resourceimport { dataBucket } from "./data-bucket"
Import shared configimport { encryptionDefault } from "./defaults"
Import from lexiconimport { Bucket, Sub, AWS } from "@intentius/chant-lexicon-aws"
Import from coreimport { Composite, output } from "@intentius/chant"

All imports use standard TypeScript import statements. The evaluator follows imports through the module graph and resolves each referenced binding to its definition.