Welcome to Kite
Kite is a modern IaC language designed for the multi-cloud era. Write your infrastructure once using clean, declarative syntax β then provision seamlessly across AWS, Google Cloud, Azure, and more.
Built from the ground up with simplicity and power in mind, Kite brings a fresh approach to infrastructure management. Every feature is thoughtfully designed to make your workflow faster, safer, and more intuitive.
- β’Intuitive syntax. Familiar patterns combined with modern expressiveness.
- β’True portability. Define once, provision anywhere.
- β’Built to extend. Mixins and plugins adapt seamlessly to your team's workflow.
- β’Secure and reliable. State management in a proper database ensures complete traceability.
Kite empowers teams to manage infrastructure with confidence and clarity, eliminating complexity without sacrificing control.
Getting Started
Ready to get started with Kite? Here are the essential resources to begin your journey:
πΊοΈ Introduction
Learn about Kite and why it's the best choice for multi-cloud IaC
π¦ Installation
Install Kite CLI and set up your development environment
π First Project
Build your first cloud infrastructure with a step-by-step tutorial
π Learn the Syntax
Understand Kite's syntax, types, and core language features
π‘ Example Projects
Explore sample projects and templates for common use cases
π· Develop Plugins
Create custom provider plugins to extend Kite's capabilities
π API Reference
Complete reference documentation for the Kite language
Introduction
What is Kite?
Kite is a declarative IaC language built to provision cloud infrastructure with precision and consistency.
Define your resources once. Provision them anywhere. A single Kite configuration describes exactly what you need, then scales effortlessly across your entire development lifecycle, from staging to production.
Clean syntax meets powerful type safety. Catch configuration errors before they reach the cloud. Share infrastructure modules across teams. The result? Infrastructure that's not just automated. It's remarkably simple to understand and maintain.
Why Kite?
- β’One language. Every cloud. True portability without the pain.
- β’Designed to feel familiar. Kite's syntax draws from the best of Terraform, Bicep, and modern languages like TypeScript, C# and Java.
- β’Refactor fearlessly. Rename resources in code without ever losing the real ones in the cloud.
- β’Import with ease. Bring your existing cloud infrastructure into Kite. No rewrites, no headaches, just instant control.
- β’Build without limits. Extend resources effortlessly with annotations or mixins, and compose infrastructure the way you imagine it.
- β’State that scales with you. Just a proper database managing everything automatically. Safe, fast, secure, and recoverable when things go wrong.
Install Kite
Kite runs on macOS, Windows, and Linux or universally on Java Choose your platform below to get started.
The easiest way to install Kite on macOS is using Homebrew:
brew install kitecorp/tap/kiteVerify the installation:
kite --versionIDE Support
Get syntax highlighting, code completion, and error checking in your favorite editor.
IntelliJ Plugin
Full IDE integration for all JetBrains IDEs including IntelliJ IDEA, WebStorm, PyCharm, GoLand, and others.
Features
Navigation
| Feature | Shortcut | Description |
|---|---|---|
| Go to Declaration | Cmd+Click | Navigate to variable, resource, component, function declarations |
| Find Usages | Cmd+Click on declaration | Show dropdown of all usages with context icons and line preview |
| Go to Resource | Cmd+O | Search and navigate to any resource, component, or schema |
| Go to Symbol | Cmd+Alt+O | Search all symbols including variables, functions, inputs, outputs |
| Property Navigation | Cmd+Click | Click size in server.size to jump to property definition |
| String Interpolation | Cmd+Click | Navigate from ${port} or $port to declaration |
| Breadcrumbs | β | Shows current location in file hierarchy at bottom of editor |
Editor
| Feature | Shortcut | Description |
|---|---|---|
| Syntax Highlighting | β | Lexical and semantic coloring for keywords, types, strings, decorators |
| Code Completion | Ctrl+Space | Context-aware suggestions for schema properties, variables, functions |
| Inlay Hints | β | Shows inferred types after variables and parameter names in calls |
| Quick Documentation | F1 | Popup showing type, default value, decorators, and comments |
| Parameter Info | Ctrl+P | Shows function parameter hints while typing arguments |
| Code Folding | Cmd+-/+ | Collapse/expand components, resources, schemas, functions, loops |
| Code Formatting | Cmd+Alt+L | Auto-format with vertical alignment of properties |
| Comment Toggle | Cmd+/ | Toggle line and block comments |
| Brace Matching | β | Automatic highlighting of matching braces, brackets, parentheses |
Inspections & Quick Fixes
| Feature | Shortcut | Description |
|---|---|---|
| Type Checking | β | Real-time validation of types and undefined references |
| Missing Properties | β | Warns when required schema properties are not defined |
| Unused Imports | β | Detects and grays out unused imports |
| Optimize Imports | Cmd+Alt+O | Remove unused imports automatically |
Refactoring
| Feature | Shortcut | Description |
|---|---|---|
| Rename | F2 | Safely rename symbols across all files |
| Extract Variable | Cmd+Alt+V | Extract expression into a new variable |
Structure View
| Feature | Description |
|---|---|
| Hierarchical Outline | Color-coded icons for resources, components, schemas, functions, variables |
| Element Icons | Resource (purple), Component (blue), Schema (green), Function (orange), Input (yellow), Output (lime) |
Installation
- Open IntelliJ IDEA (or any JetBrains IDE)
- Go to Settings β Plugins
- Click Marketplace tab
- Search for
Kite - Click Install
- Restart your IDE
Supported IDEs
Works with all JetBrains IDEs version 2023.1 and later:
- IntelliJ IDEA (Community & Ultimate)
- WebStorm
- PyCharm
- GoLand
- PhpStorm
- RubyMine
- CLion
- Rider
Next: Learn the Syntax of Kite.
Architecture
This page describes the overall architecture of the Kite infrastructure-as-code system.
State Management
Kite maintains state in a database (PostgreSQL by default) to track:
- β’Resource IDs from cloud providers
- β’Resource metadata and configuration
- β’Dependency relationships between resources
- β’Creation timestamps and current state
This enables operations like kite destroy to know exactly which resources to remove, and allows for safe rollback on failures.
Dependency Resolution
When resources reference each other, Kite automatically builds a dependency graph and creates resources in the correct order using topology sort.
Input Code:
βββββββββββ
resource vm web {
name = "web-server"
network = net.id
}
resource network net {
name = "vpc-main"
}
resource loadbalancer lb {
name = "web-lb"
backend = web.id
}
Dependency Graph:
βββββββββββββββββ
βββββββββββ
β network β (no dependencies)
ββββββ¬βββββ
β
β net.id
βΌ
βββββββ
β vm β (depends on network)
ββββ¬βββ
β
β web.id
βΌ
ββββββββββββββββ
β loadbalancer β (depends on vm)
ββββββββββββββββ
Execution Order: [network, vm, loadbalancer]Provider System
Kite uses a plugin-based provider system built on gRPC. Each provider runs as a separate process and communicates with the engine via protocol buffers.
- AWS - Amazon Web Services (S3, EC2, Lambda, etc.)
- Azure - Microsoft Azure (Storage, VMs, Functions, etc.)
- Files - Local file system operations
Custom providers can be built using the kite-provider-sdk and the Gradle plugin for automated documentation generation.
Syntax Basics
Kite's syntax is designed to be clean, readable, and familiar to developers coming from modern programming languages. This page covers the fundamental building blocks: variables, types, operators, and literals.
Variables
The var Keyword
Variables are declared using the var keyword:
var name = "production"var count = 42var enabled = trueExplicit Type Annotations
Types can be explicitly specified:
var string name = "production"var number count = 42var boolean enabled = trueType Inference
When the type is omitted, Kite infers it from the initial value. The inferred type is fixed at declaration.
var name = "hello" // Inferred as stringvar count = 10 // Inferred as numbervar items = [1, 2, 3] // Inferred as number[]Types
Primitive Types
| Type | Description | Example |
|---|---|---|
string | UTF-8 text values with interpolation support | "hello", "Hello, ${name}!" |
number | 64-bit floating-point (integers and decimals) | 42, 3.14, -17, 1.5e10 |
boolean | Logical true/false values | true, false |
null | Explicit absence of a value | null |
any | Disables type checking (use sparingly) | var any x = "hello" |
Array Types
Arrays are declared with [] suffix:
var string[] names = ["alice", "bob"]var number[] scores = [95, 87, 92]var boolean[] flags = [true, false, true]Object Types
Objects use key-value syntax:
var config = { host: "localhost", port: 8080, ssl: true}Union Types
Union types allow multiple possible types:
var string | number id = "abc123"id = 42 // Also validFunction Types
Function type syntax:
// (param types) -> return typevar (number, number) -> number add = (a, b) -> a + b// No parametersvar () -> string greet = () -> "Hello"// No return valuevar (string) -> void log = (msg) -> print(msg)Operators
Arithmetic Operators
Kite supports standard arithmetic operations on numeric values. When mixing integers and decimals, integers are automatically promoted to floating-point. Division always returns a floating-point result, while modulo (%) returns the remainder after division.
var sum = 10 + 5 // 15var diff = 10 - 5 // 5var product = 10 * 5 // 50var quotient = 10 / 5 // 2.0 (always float)var remainder = 10 % 3 // 1Comparison Operators
Comparison operators return boolean values. Equality (==) and inequality (!=) work on all types including strings and booleans. Ordering comparisons (<, >,<=, >=) work on numbers and strings (lexicographic comparison).
a == b // Equal (works on all types)a != b // Not equala < b // Less thana > b // Greater thana <= b // Less than or equala >= b // Greater than or equal// String comparison is lexicographic"apple" < "banana" // true"abc" == "abc" // trueLogical Operators
Logical operators work with boolean values and use short-circuit evaluation:&& stops evaluating if the left side is false, and || stops if the left side is true. This is useful for conditional execution and providing default values.
a && b // AND: true only if both are truea || b // OR: true if either is true!a // NOT: inverts the boolean// Short-circuit evaluationenabled && runTask() // runTask() only called if enabled is truevalue || "default" // Returns value if truthy, otherwise "default"Assignment Operators
Assignment operators modify variables in place. Compound operators like += combine an operation with assignment. For arrays, += appends elements. The increment (++) and decrement (--) operators modify numeric variables by 1.
x = 10 // Assignx += 5 // Add and assign (x = x + 5)x -= 3 // Subtract and assignx *= 2 // Multiply and assignx /= 4 // Divide and assignx++ // Increment by 1x-- // Decrement by 1// Array append with +=var items = ["a", "b"]items += "c" // items is now ["a", "b", "c"]String Operators
Strings can be concatenated with +. Double-quoted strings support interpolation using ${expression} syntax for complex expressions or $variable for simple variables. Single-quoted strings are literal and do not process interpolation.
var greeting = "Hello" + " " + "World" // Concatenation// String interpolation (double quotes only)var name = "Alice"var message = "Hello, ${name}!" // "Hello, Alice!"var count = 3var items = "You have ${count} items" // "You have 3 items"// Expression interpolationvar total = "Sum: ${10 + 20}" // "Sum: 30"// Single quotes = no interpolationvar literal = '${name}' // "${name}" (literal text)Member Access
Access object properties with dot notation or bracket notation. Use bracket notation when the key is dynamic or contains special characters. Array elements are accessed by zero-based index.
object.property // Dot notation for known keysarray[0] // Array index (zero-based)object["key"] // Bracket notation (dynamic keys)// Examplesvar config = { host: "localhost", port: 8080 }var host = config.host // "localhost"var port = config["port"] // 8080var items = ["first", "second", "third"]var first = items[0] // "first"var last = items[items.length - 1] // "third"Range Operator
The range operator (..) creates a sequence of integers. The end value is exclusive, meaning 0..5 produces 0, 1, 2, 3, 4 (not including 5). Ranges are commonly used in for loops to iterate a specific number of times.
0..10 // Range from 0 to 9 (end exclusive)// Common for loop patternfor i in 0..5 { print(i) // Prints: 0, 1, 2, 3, 4}// Dynamic rangesvar count = 3for i in 0..count { print("Item ${i}")}Literals
String Literals
// Double quotes - with interpolationvar greeting = "Hello, ${name}!"// Single quotes - literal (no interpolation)var pattern = '^[a-z]+$'Number Literals
var integer = 42var negative = -17var decimal = 3.14159var scientific = 1.5e10Boolean Literals
var yes = truevar no = falseArray Literals
var empty = []var numbers = [1, 2, 3, 4, 5]var mixed = ["hello", 42, true]var nested = [[1, 2], [3, 4]]Object Literals
var empty = {}var config = { name: "server", port: 8080, tags: ["web", "api"]}Null Literal
var nothing = nullNext: Learn about Resources - the core building blocks for infrastructure.
Resources
Resources are the core building blocks in Kite. They represent cloud infrastructure components that will be provisioned.
Basic Syntax
resource TypeName resourceName { property = value anotherProperty = "string value"}Simple Resource
resource S3.Bucket photos { name = "my-photos-bucket" region = "us-east-1"}Resource with Schema Type
schema ServerConfig { string instanceType = "t3.micro" number port = 8080 boolean public = false}resource ServerConfig webServer { instanceType = "t3.large" port = 443 public = true}Dynamic Resource Names
Resource names can be dynamic using expressions:
var env = "production"resource S3.Bucket storage { name = "data-${env}" // "data-production"}Resource Properties
resource EC2.Instance server { name = "web-server" // String property port = 8080 // Number property public = true // Boolean property securityGroups = ["sg-001", "sg-002"] // Array property // Object property tags = { Environment: "production", Team: "platform" }}Multiple Resources
Using @count Decorator
@count(3)resource EC2.Instance server { name = "server-${count}" // "server-0", "server-1", "server-2"}Using For Loops
var environments = ["dev", "staging", "prod"][for env in environments]resource S3.Bucket bucket { name = "data-${env}"}Resource References
Resources can reference other resources:
resource VPC.Network mainVpc { cidr = "10.0.0.0/16"}resource VPC.Subnet publicSubnet { vpcId = mainVpc.id cidr = "10.0.1.0/24"}resource EC2.Instance server { subnetId = publicSubnet.id vpcId = mainVpc.id}Resource Decorators
@provider
@provider("aws")resource S3.Bucket photos { name = "photos"}@existing
Reference existing cloud resources:
@existing("arn:aws:s3:::existing-bucket")resource S3.Bucket imported {}@dependsOn
resource VPC.Subnet subnet { ... }@dependsOn(subnet)resource EC2.Instance server { subnetId = subnet.id}@tags
@tags({ Environment: "prod", Team: "platform" })resource S3.Bucket photos { name = "photos"}Cloud-Generated Properties
Some properties are set by the cloud provider after resource creation:
schema AwsInstance { string name // User-set @cloud string arn // Cloud-generated @cloud(importable) string id // Cloud-generated, can be used for import}resource AwsInstance server { name = "web-server" // arn and id are NOT set here - they come from AWS after apply}// Access cloud-generated properties in outputsoutput string serverArn = server.arnNext: Learn about Components - reusable infrastructure modules.
Components
Components are reusable, parameterized infrastructure modules. They encapsulate resources, inputs, and outputs into a single unit.
Component Type Declaration
component WebServer { // Inputs - configurable parameters input string hostname input number port = 8080 // Internal resources resource EC2.Instance server { name = hostname } // Outputs - exposed values output string endpoint = "${hostname}:${port}"}Component Instantiation
// Define the component typecomponent WebServer { input string hostname input number port = 8080}// Create instancescomponent WebServer main { hostname = "localhost" port = 3000}component WebServer api { hostname = "api.example.com" port = main.port // Reference another instance}Inputs
Inputs are configurable parameters for components:
component Database { input string name // Required input (no default) input number port = 5432 // Optional input (with default) input string[] allowedIps = [] // Typed array input input boolean sslEnabled = true // Boolean input}Input Decorators
component Server { @description("The server hostname") @nonEmpty input string hostname @minValue(1) @maxValue(65535) input number port = 8080 @sensitive input string apiKey}Outputs
Outputs expose values from components:
component WebServer { input string hostname input number port = 8080 resource EC2.Instance server { name = hostname } output string endpoint = "${hostname}:${port}" // Simple output output string serverId = server.id // Output from resource output string url = "https://${hostname}:${port}" // Computed output}Accessing Component Properties
Define a component, then instantiate it:
component WebServer { input string hostname input number port = 8080 output string endpoint = "http://${hostname}:${port}" resource VM.Instance server { name = hostname }}Create an instance and access its properties:
component WebServer main { hostname = "localhost" port = 3000}var host = main.hostname // "localhost"var p = main.port // 3000var url = main.endpoint // "http://localhost:3000"// Resources are private (not accessible from outside)// main.server // ERROR: resources are privateWhy Resources Are Private
Resources are private to enforce clean component APIs, enable safe refactoring, and follow the principle of "expose behavior, not implementation."
Prevents Tight Coupling
Without this restriction, consumers could write:
// BAD: Tight coupling to internal structurevar ip = webServer.server.privateIpvar disk = webServer.server.rootVolume.sizeThis creates fragile dependencies on internal implementation. Components force authors to explicitly define what's public:
| Element | Visibility | Purpose |
|---|---|---|
input | Public | Configuration parameters |
output | Public | Computed/exposed values |
resource | Private | Infrastructure implementation |
Enables Safe Refactoring
The component author can change internal resources without breaking consumers:
// v1: Uses VMcomponent WebServer { resource VM.Instance server { ... } output string endpoint = server.publicIp}// v2: Switched to container - consumers unaffectedcomponent WebServer { resource ECS.Service service { ... } output string endpoint = service.loadBalancerUrl}If main.server was allowed, refactoring would break all callers.
Encapsulation (Information Hiding)
Components expose a public contract (inputs/outputs) while hiding implementation details (resources). This is the same principle as private fields in OOP.
component WebServer { input number port = 8080 output string endpoint = "http://${server.publicIp}:${port}" // Implementation detail - could change without breaking consumers resource VM.Instance server { size = "t2.micro" }}Consumers only care about port (what they provide) and endpoint (what they get back). They shouldn't depend on whether there's a VM, container, or Lambda underneath.
Component Decorators
@count
@count(3)component WebServer replica { hostname = "server-${count}"}// Creates: replica-0, replica-1, replica-2@dependsOn
component Database db { ... }@dependsOn(db)component WebServer api { databaseHost = db.endpoint}@tags
@tags({ Environment: "prod", Team: "platform" })component WebApp main { name = "main-app"}Nested Components
component Frontend { input string name component WebServer server { hostname = "${name}.example.com" } output string url = server.endpoint}component Application { component Frontend web { name = "web" } component Backend api { name = "api" }}Next: Learn about Schemas - structured data types for resources.
Schemas
Schemas define structured data types for resource configurations. They provide type safety and validation for cloud resource properties.
Basic Syntax
schema SchemaName { type propertyName type propertyWithDefault = defaultValue}Simple Schema
schema DatabaseConfig { string host number port = 5432 boolean ssl = true}Schema with All Types
schema ServerConfig { // Required properties (no default) string name string region // Optional properties (with defaults) string instanceType = "t3.micro" number port = 8080 boolean public = false // Array property string[] securityGroups = [] // Object property object tags = {}}Using Schemas with Resources
Schemas define the type of a resource:
schema AwsS3Bucket { string name string region = "us-east-1" boolean versioning = false}resource AwsS3Bucket photos { name = "my-photos-bucket" versioning = true}Property Decorators
@cloud
Mark properties as cloud-generated (set by provider after creation):
schema AwsInstance { string name // User-set @cloud string arn // Cloud-generated, not importable @cloud(importable) string id // Cloud-generated, can be used for import @cloud string publicIp // Cloud-generated}resource AwsInstance server { name = "web-server" // arn, id, publicIp are NOT set here // They come from AWS after apply}// Access cloud-generated propertiesoutput string serverArn = server.arnoutput string serverId = server.id@allowed
Restrict property values to a whitelist:
schema ServerConfig { @allowed(["default", "dedicated", "host"]) string tenancy = "default" @allowed(["gp2", "gp3", "io1", "io2"]) string volumeType = "gp3" @allowed([80, 443, 8080, 8443]) number port = 80}@description
Add documentation to properties:
schema DatabaseConfig { @description("The database hostname or IP address") string host @description("Port number for database connections") number port = 5432 @description("Enable SSL/TLS encryption") boolean ssl = true}@sensitive
Mark sensitive properties:
schema DatabaseConfig { string host number port = 5432 @sensitive string password @sensitive string connectionString}Validation Decorators
schema UserConfig { @minLength(3) @maxLength(50) string username @minValue(18) @maxValue(120) number age @validate(regex: "^[a-z0-9._%+-]+@[a-z0-9.-]+\\.[a-z]{2,}$") string email @nonEmpty string[] roles}Schema Inheritance
Schemas can reference other schemas:
schema NetworkConfig { string vpcId string subnetId string[] securityGroups = []}schema ServerConfig { string name string instanceType = "t3.micro" NetworkConfig network // Nested schema}resource ServerConfig server { name = "web-server" network = { vpcId: "vpc-123", subnetId: "subnet-456" }}Inline Style
Schemas can be declared in a single line:
schema Point { number x; number y }schema Color { number r; number g; number b; number a = 1.0 }Schema vs Struct
| Feature | Schema | Struct |
|---|---|---|
| Purpose | Resource configuration | Data containers |
| Type System | Structural typing | Nominal typing |
| Instantiation | Via resources | Via constructor |
| Cloud Properties | Supports @cloud | No @cloud support |
| Mutability | Depends on resource | Mutable |
Use schemas for cloud resource configurations. Use structs for general data structures in your code.
Next: Learn about Structs - nominal typed data containers.
Structs
Structs are nominal typed data containers for type-safe data passing. Unlike schemas (used for resource configurations), structs are general-purpose data structures.
Basic Syntax
Block Style
struct StructName { type propertyName type propertyWithDefault = defaultValue}Inline Style
struct Point { number x, number y }Examples
Simple Struct
struct Point { number x number y}struct Rectangle { number width number height number x = 0 number y = 0}Struct with Various Types
struct User { string name string email number age boolean active = true string[] roles = []}Instantiation
Constructor Syntax
Create struct instances by calling the struct name as a function:
struct Point { number x, number y }// Positional argumentsvar p1 = Point(10, 20)// With defaults (if defined)struct Config { number port = 8080 string host = "localhost"}var c1 = Config() // Uses all defaultsvar c2 = Config(3000) // port=3000, host="localhost"var c3 = Config(3000, "0.0.0.0") // port=3000, host="0.0.0.0"Auto-Coercion from Object Literals
When a variable has an explicit struct type, object literals are automatically converted:
struct Config { number port = 8080 string host = "localhost"}// Auto-coerced to Config instancevar Config c = { port: 3000 }// c.host == "localhost" (default)// c.port == 3000 (overridden)var Config full = { port: 443, host: "api.example.com" }Accessing Properties
struct Point { number x, number y }var p = Point(10, 20)var xCoord = p.x // 10var yCoord = p.y // 20Mutability
Struct instances are mutable - properties can be changed after creation:
struct Point { number x, number y }var p = Point(10, 20)p.x = 100 // Valid - mutates the propertyp.y = 200// p is now Point(100, 200)Structs with Inputs and Outputs
Structs work fully with inputs and outputs in both files and components.
Struct Inputs
struct Point { number x, number y = 0 }// In a componentcomponent Shape { input Point origin // Required struct input input Point center = Point(0, 0) // With default input Point[] corners // Array of structs}// Standalone in a fileinput Point origin = Point(10, 20)Struct Outputs
struct Point { number x, number y }// In a componentcomponent Shape { input number width = 100 output Point center = Point(width/2, width/2) // Computed from inputs}// Standalone in a fileoutput Point center = Point(50, 50)output Point[] corners = [Point(0,0), Point(100,100)]Auto-Coercion in Inputs
input Point origin = { x: 10, y: 20 } // Auto-coerced to PointStructs in Schemas and Resources
struct Point { number x, number y }schema Shape { Point origin}resource Shape myShape { origin = Point(10, 20) // Constructor syntax // OR origin = { x: 10, y: 20 } // Object literal (auto-coerced)}Nested Struct Inputs/Outputs
struct Point { number x, number y }struct Rectangle { Point topLeft, Point bottomRight }component Canvas { input Rectangle bounds = Rectangle(Point(0,0), Point(100,100)) output Point center = Point( (bounds.topLeft.x + bounds.bottomRight.x) / 2, (bounds.topLeft.y + bounds.bottomRight.y) / 2 )}Property Decorators
@description
struct ServerConfig { @description("Port number for the server") number port = 8080 @description("Hostname to bind to") string host = "localhost"}@cloud
Mark properties as cloud-generated (set by provider):
struct AWSResource { string name @cloud string arn // Set by cloud provider, cannot be initialized}Validation Decorators
struct UserInput { @nonEmpty @minLength(3) string username @minValue(0) @maxValue(120) number age @validate(regex: "^[a-z0-9._%+-]+@[a-z0-9.-]+\\.[a-z]{2,}$") string email}Nested Structs
Structs can contain other structs:
struct Address { string street string city string country string postalCode}struct Person { string name number age Address address}var person = Person( "John Doe", 30, Address("123 Main St", "New York", "USA", "10001"))var city = person.address.city // "New York"Struct vs Schema
| Feature | Struct | Schema |
|---|---|---|
| Purpose | Data containers | Resource definition |
| Type System | Nominal (name matters) | Structural |
| Instantiation | Constructor call | Via resources |
| Auto-coercion | Yes (from objects) | No |
| Mutability | Mutable | Depends on resource |
// Nominal typing - names must matchstruct Point { number x, number y }struct Coordinate { number x, number y }var Point p = Point(10, 20) // OKvar Point c = Coordinate(10, 20) // ERROR: type mismatchArrays of Structs
struct Point { number x, number y }var points = [ Point(0, 0), Point(10, 20), Point(30, 40)]for point in points { var sum = point.x + point.y}Structs as Function Parameters
struct Rectangle { number width number height}fun area(Rectangle rect) number { return rect.width * rect.height}var r = Rectangle(10, 20)var a = area(r) // 200Next: Learn about Functions - reusable blocks of code.
Functions
Functions are reusable blocks of code that can accept parameters and return values.
Function Declaration
Basic Syntax
fun functionName(parameters) returnType { // body return value}Examples
// Simple functionfun greet() string { return "Hello, World!"}// Function with parametersfun add(number x, number y) number { return x + y}// Function with no return valuefun logMessage(string message) { print(message)}Parameters
Typed Parameters
fun multiply(number a, number b) number { return a * b}fun formatName(string first, string last) string { return "${first} ${last}"}Multiple Parameters
fun createUser(string name, number age, boolean active) object { return { name: name, age: age, active: active }}Array Parameters
fun sum(number[] numbers) number { var total = 0 for n in numbers { total += n } return total}fun first(string[] items) string { return items[0]}Return Types
Explicit Return Type
fun getPort() number { return 8080}fun getName() string { return "default"}fun isEnabled() boolean { return true}Complex Return Types
fun getConfig() object { return { host: "localhost", port: 8080 }}fun getPorts() number[] { return [80, 443, 8080]}Function Return Types
Functions can return other functions:
fun outer(number x, number y) (number) -> number { fun inner(number p) number { return p + x + y } return inner}var adder = outer(10, 20)var result = adder(5) // 35Function Calls
// Simple callvar message = greet()// With argumentsvar total = add(5, 3)// Chained callsvar doubled = multiply(add(2, 3), 2) // 10// With variablesvar x = 10var y = 20var sum = add(x, y)Lambda Expressions
Basic Syntax
(parameters) -> expression(parameters) -> { statements }Examples
// Simple lambdavar double = (x) -> x * 2// With type annotationsvar add = (number a, number b) -> a + b// Block bodyvar process = (string input) -> { var upper = toUpperCase(input) return upper}Using Lambdas
// Assign to variablevar square = (x) -> x * xvar result = square(5) // 25// Pass to higher-order functionvar numbers = [1, 2, 3, 4, 5]var doubled = map(numbers, (n) -> n * 2)// Result: [2, 4, 6, 8, 10]// Filter with lambdavar evens = filter(numbers, (n) -> n % 2 == 0)// Result: [2, 4]Type Aliases for Functions
// Define function typestype MathOp = (number, number) -> numbertype Predicate = (string) -> booleantype Transformer = (object) -> object// Use in declarationsvar MathOp add = (a, b) -> a + bvar MathOp multiply = (a, b) -> a * bHigher-Order Functions
Functions that take or return other functions:
// Function that takes a functionfun applyTwice((number) -> number f, number x) number { return f(f(x))}var result = applyTwice((n) -> n * 2, 5) // 20// Function that returns a functionfun makeMultiplier(number factor) (number) -> number { return (x) -> x * factor}var triple = makeMultiplier(3)var result = triple(10) // 30Init Blocks
Init blocks run initialization code within components:
component Server { input string name var string normalizedName init() { normalizedName = toLowerCase(name) } resource EC2.Instance server { name = normalizedName }}Init with Parameters
init(string prefix, number count) { // initialization code}Function Decorators
@description("Calculate the area of a rectangle")fun area(number width, number height) number { return width * height}Recursion
Functions can call themselves:
fun factorial(number n) number { if n <= 1 { return 1 } return n * factorial(n - 1)}var result = factorial(5) // 120Closures
Inner functions capture variables from outer scope:
fun makeCounter() () -> number { var count = 0 return () -> { count++ return count }}var counter = makeCounter()counter() // 1counter() // 2counter() // 3Next: Learn about Control Flow - if/else, loops, and comprehensions.
Control Flow
Kite provides standard control flow constructs: if/else, while loops, and for loops.
If Statements
Basic Syntax
if condition { // body}With Parentheses
Parentheses around the condition are optional:
// Both are validif (x > 5) { doSomething()}if x > 5 { doSomething()}If-Else
if condition { // true branch} else { // false branch}Examples
var x = 10if x > 5 { var result = "greater"}if (x == 10) { var result = "equal"} else { var result = "not equal"}// Nested conditionsif x > 0 { if x < 100 { var result = "in range" }}Important: Braces Required
Unlike some languages, Kite requires braces for if/else bodies:
// Validif x > 5 { doSomething() }// Invalid - missing bracesif x > 5 doSomething() // ERRORWhile Loops
Basic Syntax
while condition { // body}Examples
var count = 0while count < 10 { count++}// With parentheses (optional)while (count < 20) { count++}For Loops
Iterating Over Ranges
for i in 0..5 { // i = 0, 1, 2, 3, 4 (end exclusive)}Iterating Over Arrays
var items = ["a", "b", "c"]for item in items { // item = "a", "b", "c"}With Index
var items = ["a", "b", "c"]for index, item in items { // index = 0, item = "a" // index = 1, item = "b" // index = 2, item = "c"}For Loops with Resources
For loops can create multiple resources:
var environments = ["dev", "staging", "prod"][for env in environments]resource S3.Bucket bucket { name = "data-${env}"}This creates three buckets: data-dev, data-staging, data-prod.
Array Comprehensions
Kite supports three forms of array comprehensions.
Form 1: Compact (Inline Body)
// Basic[for i in 0..6: i * 2]// Result: [0, 2, 4, 6, 8, 10]// With filter[for i in 0..10: if i > 5 { i }]// Result: [6, 7, 8, 9]// With transformation[for item in items: item.name]Form 2: Block Body (For Resources)
var environments = ["dev", "staging", "prod"][for env in environments]resource S3.Bucket bucket { name = "photos-${env}"}Form 3: Standalone For Loop
for i in 0..10 { var doubled = i * 2}Comprehension with Conditionals
// Inline if[for i in 0..10: if (i % 2 == 0) i]// Result: [0, 2, 4, 6, 8]// If-else[for i in 0..10: if i > 5 { i * 2 } else { i }]// Result: [0, 1, 2, 3, 4, 5, 12, 14, 16, 18]Nested Comprehensions
var matrix = [ [for j in 0..3: i * 3 + j] for i in 0..3]// Result: [[0,1,2], [3,4,5], [6,7,8]]Creating Multiple Resources
Using @count Decorator
@count(3)resource EC2.Instance server { name = "server-${count}"}// Creates: server-0, server-1, server-2Using For Loops
var zones = ["us-east-1a", "us-east-1b", "us-east-1c"][for zone in zones]resource EC2.Instance server { name = "server-${zone}" availabilityZone = zone}Conditional Resource Creation
var createBackup = trueif createBackup { resource S3.Bucket backup { name = "backup-bucket" }}Control Flow in Components
component WebApp { input number replicas = 1 input boolean enableCache = false @count(replicas) resource EC2.Instance server { name = "server-${count}" } // Conditional resource if enableCache { resource ElastiCache.Cluster cache { name = "app-cache" } }}Best Practices
Use Braces Consistently
Always use braces, even for single statements:
// Recommendedif x > 5 { doSomething()}// Not allowed anywayif x > 5 doSomething() // ERRORPrefer For Loops for Resources
When creating multiple similar resources:
// Good - explicit iterationfor env in ["dev", "staging", "prod"]resource S3.Bucket bucket { name = "data-${env}"}// Also good - count decorator@count(3)resource EC2.Instance server { name = "server-${count}"}Use Comprehensions for Data Transformation
var servers = [ { name: "web", port: 80 }, { name: "api", port: 8080 }, { name: "db", port: 5432 }]// Extract namesvar names = [for s in servers: s.name]// Result: ["web", "api", "db"]// Filter by portvar highPorts = [for s in servers: if s.port > 1000 { s.name }]// Result: ["api", "db"]Next: Learn about Strings - string types and interpolation.
Strings
Kite supports two types of strings: double-quoted strings with interpolation and single-quoted literal strings.
String Types
Double-Quoted Strings (Interpolated)
Double-quoted strings support variable and expression interpolation:
var name = "World"var greeting = "Hello, ${name}!" // "Hello, World!"Single-Quoted Strings (Literal)
Single-quoted strings are literal - no interpolation:
var literal = 'No $interpolation here'var pattern = '^[a-z]+$' // Regex patternString Interpolation
Simple Variable Interpolation
Use $variable for simple variable references:
var name = "Alice"var age = 30var message = "Name: $name, Age: $age"// Result: "Name: Alice, Age: 30"Expression Interpolation
Use ${expression} for any expression:
var x = 5var y = 10var result = "Sum: ${x + y}"// Result: "Sum: 15"var doubled = "Doubled: ${x * 2}"// Result: "Doubled: 10"Complex Expressions
var user = { name: "Bob", age: 25 }var info = "User: ${user.name} is ${user.age} years old"// Result: "User: Bob is 25 years old"var items = [1, 2, 3]var count = "Count: ${length(items)}"// Result: "Count: 3"Nested Interpolation
var prefix = "data"var env = "prod"var suffix = "bucket"var name = "${prefix}-${env}-${suffix}"// Result: "data-prod-bucket"Escape Sequences
Common Escapes
| Sequence | Result |
|---|---|
\\ | Backslash |
\" | Double quote |
\' | Single quote |
\n | Newline |
\t | Tab |
\$ | Literal dollar sign |
Examples
var path = "C:\\Users\\name"var quoted = "He said \"Hello\""var literalDollar = "Price: \$100"var multiline = "Line 1\nLine 2"Strings in Resources
String interpolation is commonly used in resource names and properties:
var environment = "production"var appName = "myapp"resource S3.Bucket storage { name = "${appName}-${environment}-storage" // Result: "myapp-production-storage"}resource EC2.Instance server { name = "${appName}-server-${environment}" tags = { Name: "${appName}-server", Environment: environment }}Strings with @count
The count variable is automatically available in counted resources:
@count(3)resource EC2.Instance server { name = "server-${count}" // Creates: "server-0", "server-1", "server-2"}Strings in Components
component WebApp { input string name input string environment = "dev" resource EC2.Instance server { name = "${name}-${environment}-server" } output string endpoint = "https://${name}.example.com"}component WebApp prod { name = "myapp" environment = "prod"}// prod.endpoint = "https://myapp.example.com"String Operations
Concatenation
var first = "Hello"var second = "World"// Using interpolationvar combined = "${first} ${second}"// Or with + operatorvar combined = first + " " + secondString Functions (Standard Library)
var text = "Hello World"// Lengthvar len = length(text) // 11// Case conversionvar upper = toUpperCase(text) // "HELLO WORLD"var lower = toLowerCase(text) // "hello world"// Substringvar sub = substring(text, 0, 5) // "Hello"// Containsvar has = contains(text, "World") // true// Replacevar replaced = replace(text, "World", "Kite") // "Hello Kite"// Splitvar parts = split("a,b,c", ",") // ["a", "b", "c"]// Joinvar joined = join(["a", "b", "c"], "-") // "a-b-c"// Trimvar trimmed = trim(" hello ") // "hello"Multiline Strings
Single-quoted strings support multiline content:
var script = '#!/bin/bashecho "Hello"echo "World"'For double-quoted strings, use \n:
var message = "Line 1\nLine 2\nLine 3"String Comparison
var a = "hello"var b = "hello"var c = "world"a == b // truea == c // falsea != c // trueBest Practices
Use Interpolation for Dynamic Strings
// Goodvar name = "bucket-${environment}"// Avoidvar name = "bucket-" + environmentUse Single Quotes for Patterns
// Good - no escaping needed@validate(regex: '^[a-z0-9-]+$')input string name// Would need escaping with double quotes@validate(regex: "^[a-z0-9-]+$")input string nameMeaningful Resource Names
// Good - descriptive and uniqueresource S3.Bucket storage { name = "${appName}-${environment}-${purpose}"}// Avoid - generic namesresource S3.Bucket storage { name = "bucket1"}Next: Learn about Imports - modular code organization.
Imports
Kite's import system allows modular code organization with file and directory imports.
Import Syntax
Wildcard Import
Import all exported symbols from a file:
import * from "path/to/file.kite"Named Import
Import specific symbols:
import symbol1, symbol2 from "path/to/file.kite"File Imports
Wildcard File Import
// stdlib.kitefun double(number x) number { return x * 2}var greeting = "Hello"// main.kiteimport * from "stdlib.kite"var result = double(5) // 10var msg = greeting // "Hello"Named File Import
// mathUtils.kitefun add(number a, number b) number { return a + b }fun multiply(number a, number b) number { return a * b }var PI = 3.14159// main.kiteimport add, PI from "mathUtils.kite"var sum = add(1, 2) // add is availablevar area = PI * r * r // PI is available// multiply is NOT available (not imported)Directory Imports
Wildcard Directory Import
Import all symbols from all .kite files in a directory:
import * from "providers/networking"// Loads all .kite files in providers/networking/// Imports all symbols from all filesNamed Directory Import
Import specific symbols from a directory:
import NatGateway from "providers/networking"// Scans all .kite files in providers/networking/// Imports only the symbol named 'NatGateway'Multiple symbols:
import NatGateway, VPC, Subnet from "providers/networking"// Imports only the specified symbols// Other symbols are NOT importedPath Resolution
File vs Directory Detection
- Paths ending with
.kiteare treated as files - Paths without
.kiteextension are treated as directories
import * from "utils.kite" // File importimport * from "utils" // Directory importRelative Paths
Imports are relative to the current file:
project/βββ main.kiteβββ utils/β βββ helpers.kiteβ βββ validators.kiteβββ providers/ βββ aws/ βββ s3.kite// main.kiteimport * from "utils/helpers.kite"import S3 from "providers/aws"Importing Different Types
Functions
// math.kitefun add(number a, number b) number { return a + b }fun subtract(number a, number b) number { return a - b }// main.kiteimport add, subtract from "math.kite"var sum = add(5, 3) // 8var diff = subtract(5, 3) // 2Variables
// config.kitevar DEFAULT_PORT = 8080var DEFAULT_HOST = "localhost"// main.kiteimport DEFAULT_PORT, DEFAULT_HOST from "config.kite"resource Server web { port = DEFAULT_PORT host = DEFAULT_HOST}Schemas
// schemas/server.kiteschema ServerConfig { string name number port = 8080}// main.kiteimport ServerConfig from "schemas/server.kite"resource ServerConfig web { name = "web-server"}Components
// components/webapp.kitecomponent WebApp { input string name input number port = 8080}// main.kiteimport WebApp from "components/webapp.kite"component WebApp api { name = "api-server" port = 3000}Structs
// types/user.kitestruct User { string name string email number age}// main.kiteimport User from "types/user.kite"var user = User("John", "john@example.com", 30)Provider Imports
Import cloud provider resources:
// Import AWS provider componentsimport * from "providers/aws"resource EC2.Instance server { name = "web-server" instanceType = "t3.micro"}resource S3.Bucket storage { name = "my-bucket"}Selective provider imports:
import EC2, S3 from "providers/aws"import VPC, Subnet from "providers/aws/networking"Environment Isolation
Imported files execute in isolated environments:
// utils.kitevar internalCounter = 0fun increment() number { internalCounter++ return internalCounter}// main.kiteimport increment from "utils.kite"increment() // 1increment() // 2// internalCounter is NOT accessible hereCircular Import Detection
Kite detects circular imports at type-check time:
// a.kiteimport * from "b.kite"var fromA = "A"// b.kiteimport * from "a.kite" // ERROR: Circular import detectedvar fromB = "B"Import Caching
Parsed programs are cached to avoid re-parsing:
// Both imports share the same parsed moduleimport helper1 from "utils.kite"import helper2 from "utils.kite"Best Practices
Use Named Imports
Prefer named imports for clarity:
// Good - explicit about what's importedimport createBucket, deleteBucket from "s3Utils.kite"// Less clear - imports everythingimport * from "s3Utils.kite"Organize by Feature
project/βββ main.kiteβββ components/β βββ webServer.kiteβ βββ database.kiteβββ schemas/β βββ serverConfig.kiteβ βββ dbConfig.kiteβββ utils/β βββ helpers.kiteβ βββ validators.kiteβββ providers/ βββ aws/ βββ gcp/Use Directory Imports for Related Symbols
// Import all networking componentsimport VPC, Subnet, SecurityGroup from "providers/aws/networking"Next: Learn about Decorators - metadata and constraints.
Decorators
Decorators add metadata, validation, and constraints to declarations. Kite has 17 built-in decorators.
Syntax
@decoratorName@decoratorName(argument)@decoratorName(namedArg: value)Multiple decorators can be stacked:
@description("Server port")@minValue(1)@maxValue(65535)input number port = 8080Validation Decorators
@minValue(n)
Minimum value constraint for numbers.
@minValue(1)input number port = 8080@minValue(0)input number count = 10@maxValue(n)
Maximum value constraint for numbers.
@maxValue(65535)input number port = 8080@maxValue(100)input number percentage = 50@minLength(n)
Minimum length for strings and arrays.
@minLength(3)input string name@minLength(1)input string[] tags@maxLength(n)
Maximum length for strings and arrays.
@maxLength(255)input string name@maxLength(10)input string[] tags@nonEmpty
Ensures strings or arrays are not empty.
@nonEmptyinput string name@nonEmptyinput string[] requiredTags@validate(regex: "pattern")
Custom validation with regex pattern or preset.
// Regex validation@validate(regex: "^[a-z]+$")input string name@validate(regex: "^[a-z0-9-]+$")input string slug// Preset validation@validate(preset: "email")input string email@allowed([values])
Whitelist of allowed values.
@allowed(["dev", "staging", "prod"])input string environment = "dev"@allowed([80, 443, 8080])input number port = 80@unique
Ensures array elements are unique.
@uniqueinput string[] tags = ["web", "api"]@uniqueinput number[] ports = [80, 443, 8080]Schema Decorators
@cloud
Marks properties as cloud-generated (set by provider after creation).
schema AwsInstance { string name // User-set @cloud string arn // Cloud-generated @cloud(importable) string id // Cloud-generated, importable}Syntax forms:
@cloud- Cloud-generated, not importable@cloud(importable)- Shorthand for importable=true@cloud(importable=true)- Explicit true@cloud(importable=false)- Same as plain @cloud
Resource Decorators
@existing("reference")
Reference existing cloud resources.
@existing("arn:aws:s3:::my-bucket")resource S3.Bucket existingBucket {}@existing("i-0123456789abcdef0")resource EC2.Instance existingServer {}Supported formats:
- ARN:
arn:aws:s3:::bucket-name - URL:
https://example.comors3://bucket/key - EC2 Instance ID:
i-0123456789abcdef0 - KMS Alias:
alias/my-key - Log Group:
/aws/lambda/my-function - Tags:
Environment=prod,Team=platform
@sensitive
Mark sensitive data (passwords, secrets, API keys).
@sensitiveinput string apiKey@sensitiveoutput string connectionString@sensitiveresource RDS.Instance database { ... }@dependsOn(resources)
Explicit dependency declaration.
resource VPC.Subnet subnet { ... }@dependsOn(subnet)resource EC2.Instance server { ... }@dependsOn([vpc, subnet, securityGroup])resource RDS.Instance database { ... }@tags(tags)
Add cloud provider tags.
// Object format@tags({ Environment: "prod", Team: "platform" })resource S3.Bucket photos { ... }// Array format@tags(["Environment =prod", "Team=platform"])resource EC2.Instance server { ... }// String format@tags("Environment =prod")resource RDS.Instance db { ... }@provider(providers)
Target specific cloud providers.
@provider("aws")resource S3.Bucket photos { ... }@provider(["aws", "azure"])resource Storage.Bucket multiCloud { ... }@count(n)
Create multiple instances. Injects count variable (0-indexed).
@count(3)resource EC2.Instance server { name = "server-${count}" // server-0, server-1, server-2}@count(replicas)component WebServer api { input number index = count}Metadata Decorators
@description("text")
Documentation for any declaration.
@description("The port number for the web server")input number port = 8080@description("Main application database")resource RDS.Instance database { ... }@description("User configuration schema")schema Config { ... }@description("Calculate the area of a rectangle")fun area(number w, number h) number { ... }Quick Reference
| Decorator | Arguments | Targets |
|---|---|---|
@minValue(n) | number | input, output |
@maxValue(n) | number | input, output |
@minLength(n) | number | input, output |
@maxLength(n) | number | input, output |
@nonEmpty | none | input |
@validate(regex:, preset:) | named strings | input, output |
@allowed([...]) | array | input, schema property |
@unique | none | input |
@cloud | optional: importable | schema property |
@existing("ref") | string | resource |
@sensitive | none | input, output |
@dependsOn(res) | reference(s) | resource, component |
@tags({...}) | object/array/string | resource, component |
@provider("...") | string/array | resource, component |
@description("...") | string | all declarations |
@count(n) | number | resource, component |
Syntax Rules
// Valid - single positional argument@provider("aws")@provider(["aws", "azure"]) // Array is ONE argument// Valid - named arguments@validate(regex: "^[a-z]+$")// Invalid - multiple positional arguments@provider("aws", "azure") // ERROR: use array insteadObject Key Validation
Decorator object keys must be alphanumeric:
// Valid@tags({ envStage: "prod" }) // underscore OK@tags({ cloudProvider: "aws" }) // hyphen OK@tags({ Environment: "production" })// Invalid@tags({ "env stage": "prod" }) // space not allowed@tags({ "123start": "value" }) // can't start with numberPattern: ^[a-zA-Z][a-zA-Z0-9_-]*$
Next: Learn about the Standard Library - built-in functions.
Standard Library
Kite provides a rich standard library of built-in functions for common operations.
Output Functions
print(value)
Output a value without a newline.
print("Hello")print(" World")// Output: Hello Worldprintln(value)
Output a value followed by a newline.
println("Hello")println("World")// Output:// Hello// WorldType Casting Functions
int(value)
Convert a value to an integer.
var x = int("42") // 42var y = int(3.7) // 3var z = int(true) // Error: boolean can't be convertednumber(value)
Convert a value to a number (floating-point).
var x = number("3.14") // 3.14var y = number(42) // 42.0decimal(value)
Convert a value to a decimal (high precision).
var price = decimal("19.99")var amount = decimal(100)string(value)
Convert any value to its string representation.
var s = string(42) // "42"var t = string(true) // "true"var u = string([1,2,3]) // "[1, 2, 3]"boolean(value)
Convert a value to a boolean.
var b = boolean(1) // truevar c = boolean(0) // falsevar d = boolean("") // falsevar e = boolean("text") // trueString Functions
length(value)
Get the length of a string or array.
var len = length("Hello") // 5var size = length([1,2,3]) // 3charAt(string, index)
Get the character at a specific index.
var ch = charAt("Hello", 0) // "H"var last = charAt("Hello", 4) // "o"indexOf(string, search)
Find the index of a substring.
var pos = indexOf("Hello World", "World") // 6var notFound = indexOf("Hello", "xyz") // -1substring(string, start, end?)
Extract a portion of a string.
var sub = substring("Hello World", 0, 5) // "Hello"var rest = substring("Hello World", 6) // "World"toLowerCase(string)
Convert string to lowercase.
var lower = toLowerCase("HELLO") // "hello"toUpperCase(string)
Convert string to uppercase.
var upper = toUpperCase("hello") // "HELLO"trim(string)
Remove whitespace from both ends.
var cleaned = trim(" hello ") // "hello"startsWith(string, prefix)
Check if string starts with prefix.
var result = startsWith("Hello World", "Hello") // trueendsWith(string, suffix)
Check if string ends with suffix.
var result = endsWith("file.txt", ".txt") // truesplit(string, delimiter)
Split string into array.
var parts = split("a,b,c", ",") // ["a", "b", "c"]replace(string, search, replacement)
Replace occurrences in string.
var result = replace("Hello World", "World", "Kite")// "Hello Kite"format(template, ...args)
Format string with arguments.
var msg = format("Hello, {0}! You have {1} messages.", "Alice", 5)// "Hello, Alice! You have 5 messages."Collection Functions
range(end) / range(start, end) / range(start, end, step)
Generate a range of numbers.
var r1 = range(5) // [0, 1, 2, 3, 4]var r2 = range(1, 5) // [1, 2, 3, 4]var r3 = range(0, 10, 2) // [0, 2, 4, 6, 8]var r4 = range(5, 0, -1) // [5, 4, 3, 2, 1]first(array)
Get the first element.
var f = first([1, 2, 3]) // 1last(array)
Get the last element.
var l = last([1, 2, 3]) // 3isEmpty(array)
Check if array is empty.
var empty = isEmpty([]) // truevar notEmpty = isEmpty([1]) // falsecontains(array, element)
Check if array contains element.
var has = contains([1, 2, 3], 2) // truevar no = contains([1, 2, 3], 5) // falsepush(array, element)
Add element to end of array (returns new array).
var newArr = push([1, 2], 3) // [1, 2, 3]slice(array, start, end?)
Extract portion of array.
var part = slice([1, 2, 3, 4, 5], 1, 4) // [2, 3, 4]var rest = slice([1, 2, 3, 4, 5], 2) // [3, 4, 5]reverse(array)
Reverse array order.
var rev = reverse([1, 2, 3]) // [3, 2, 1]sort(array)
Sort array in ascending order.
var sorted = sort([3, 1, 2]) // [1, 2, 3]var names = sort(["c", "a", "b"]) // ["a", "b", "c"]distinct(array)
Remove duplicate elements.
var unique = distinct([1, 2, 2, 3, 1]) // [1, 2, 3]flatten(array)
Flatten nested arrays.
var flat = flatten([[1, 2], [3, 4]]) // [1, 2, 3, 4]join(array, separator)
Join array elements into string.
var str = join(["a", "b", "c"], "-") // "a-b-c"sum(array)
Sum numeric array elements.
var total = sum([1, 2, 3, 4, 5]) // 15average(array)
Calculate average of numeric array.
var avg = average([10, 20, 30]) // 20.0find(array, predicate)
Find first element matching predicate.
var found = find([1, 2, 3, 4], (x) -> x > 2) // 3zip(array1, array2)
Combine two arrays into pairs.
var pairs = zip([1, 2, 3], ["a", "b", "c"])// [[1, "a"], [2, "b"], [3, "c"]]Numeric Functions
abs(number)
Get absolute value.
var a = abs(-5) // 5var b = abs(5) // 5floor(number)
Round down to nearest integer.
var f = floor(3.7) // 3var g = floor(-3.2) // -4ceil(number)
Round up to nearest integer.
var c = ceil(3.2) // 4var d = ceil(-3.7) // -3round(number)
Round to nearest integer.
var r = round(3.5) // 4var s = round(3.4) // 3min(a, b)
Get minimum value.
var m = min(5, 3) // 3max(a, b)
Get maximum value.
var m = max(5, 3) // 5clamp(value, min, max)
Clamp value within range.
var c = clamp(15, 0, 10) // 10var d = clamp(-5, 0, 10) // 0var e = clamp(5, 0, 10) // 5pow(base, exponent)
Calculate power.
var p = pow(2, 3) // 8var q = pow(10, 2) // 100sqrt(number)
Calculate square root.
var s = sqrt(16) // 4.0var t = sqrt(2) // 1.4142...Object Functions
keys(object)
Get array of object keys.
var obj = { name: "Alice", age: 30 }var k = keys(obj) // ["name", "age"]values(object)
Get array of object values.
var obj = { name: "Alice", age: 30 }var v = values(obj) // ["Alice", 30]entries(object)
Get array of [key, value] pairs.
var obj = { a: 1, b: 2 }var e = entries(obj) // [["a", 1], ["b", 2]]hasKey(object, key)
Check if object has key.
var obj = { name: "Alice" }var has = hasKey(obj, "name") // truevar no = hasKey(obj, "email") // falseget(object, key, default?)
Get value with optional default.
var obj = { name: "Alice" }var name = get(obj, "name") // "Alice"var age = get(obj, "age", 0) // 0 (default)var email = get(obj, "email", null) // nullmerge(obj1, obj2, ...objN)
Merge multiple objects.
var a = { x: 1 }var b = { y: 2 }var c = { z: 3 }var merged = merge(a, b, c) // { x: 1, y: 2, z: 3 }// Later objects override earlier onesvar override = merge({ a: 1 }, { a: 2 }) // { a: 2 }Type Checking Functions
isString("hello") // trueisNumber(42) // trueisBoolean(true) // trueisArray([1, 2, 3]) // trueisObject({ a: 1 }) // trueisNull(null) // trueDate/Time Functions
now()
Get current date/time as ISO string.
var current = now() // "2024-01-15T10:30:00.000"date(year, month, day)
Create a date.
var d = date(2024, 1, 15) // "2024-01-15"timestamp()
Get current Unix timestamp (milliseconds).
var ts = timestamp() // e.g., 1705312200000addDays(date, days)
Add days to date.
var later = addDays("2024-01-15", 10) // "2024-01-25"var earlier = addDays("2024-01-15", -5) // "2024-01-10"diffDays(date1, date2)
Calculate difference in days between dates.
var diff = diffDays("2024-01-01", "2024-01-15") // 14formatDate(date, pattern)
Format date using pattern.
var formatted = formatDate("2024-01-15", "MM/dd/yyyy")// "01/15/2024"Utility Functions
uuid()
Generate a random UUID.
var id = uuid() // "550e8400-e29b-41d4-a716-446655440000"hash(value, algorithm?)
Calculate hash of a value. Default algorithm is SHA-256.
var h = hash("hello") // SHA-256 hashvar md5 = hash("hello", "MD5") // MD5 hashvar sha1 = hash("hello", "SHA-1") // SHA-1 hashbase64Encode(string)
Encode string to Base64.
var encoded = base64Encode("Hello, World!")// "SGVsbG8sIFdvcmxkIQ =="base64Decode(string)
Decode Base64 to string.
var decoded = base64Decode("SGVsbG8sIFdvcmxkIQ==")// "Hello, World!"toJson(value)
Convert value to JSON string.
var json = toJson({ name: "Alice", age: 30 })// '{"name":"Alice","age":30}'fromJson(string)
Parse JSON string to value.
var obj = fromJson('{"name":"Alice","age":30}')// { name: "Alice", age: 30 }env(name, default?)
Get environment variable.
var home = env("HOME")var port = env("PORT", "8080") // default if not setQuick Reference
| Category | Functions |
|---|---|
| Output | print, println |
| Cast | int, number, decimal, string, boolean, any |
| String | length, charAt, indexOf, substring, toLowerCase, toUpperCase, trim, startsWith, endsWith, split, replace, format |
| Collection | range, first, last, isEmpty, contains, push, slice, reverse, sort, distinct, flatten, join, sum, average, find, zip |
| Numeric | abs, floor, ceil, round, min, max, clamp, pow, sqrt |
| Object | keys, values, entries, hasKey, get, merge |
| Types | isString, isNumber, isBoolean, isArray, isObject, isNull |
| DateTime | now, date, timestamp, addDays, diffDays, formatDate |
| Utility | uuid, hash, base64Encode, base64Decode, toJson, fromJson, env |
Explore more: Return to Syntax Basics or check the Documentation Home.