Pending<T> type system is the core innovation of ubx. It solves a fundamental problem: some values only exist after infrastructure is deployed.
The Problem
When you provision a database, you don’t know its endpoint until afterpulumi up runs. But your Helm chart needs that endpoint. Traditional tools handle this externally:
The Solution
ubx makes this a compile-time concern. Any value prefixed with~ is Pending<T>:
Propagation Rules
Pending<T> propagates through the dependency graph:
- If X depends on a
Pending<T>value, X is alsoPending<T> - Plain values are
Resolved<T> - The compiler tracks propagation through every expression, function call, and interpolation
What Produces Pending<T>
| Source | Example |
|---|---|
| Unit output attribute | ~unit.aws_rds_instance.db.endpoint |
| Component output | ~component.eks.cluster_endpoint |
| Data source attribute | ~data.aws_vpc.main.id |
| Remote stack output | ~@networking.vpc_id |
secret("aws_secrets_manager", ...) | AWS Secrets Manager |
secret("vault", ...) | HashiCorp Vault |
secret("gcp_secret_manager", ...) | GCP Secret Manager |
secret("azure_key_vault", ...) | Azure Key Vault |
| Ephemeral inputs | input "x" { ephemeral = true } |
What is Resolved<T>
| Source | Example |
|---|---|
| String literals | "postgres" |
| Number literals | 5432 |
| Boolean literals | true |
| Input references (non-ephemeral) | input.env |
| Local blocks (if value is resolved) | local.prefix |
secret("env", ...) | process.env["KEY"] |
