Inflight Magazine no. 10
The 10th issue of the Wing Inflight Magazine.
Howdy Wingnuts!
We are back with another monthly issue of the Wing Inflight Magazine and excited to share some updates about Winglang, an open source-programming language for the cloud.
New to Wing? Let’s get you up to date. Wing is a new programming language designed to help developers and platform engineers build cloud first applications with the best developer experience. The language combines cloud infrastructure and runtime into a single programming model and compiles to Terraform/CloudFormation and JavaScript that are ready to deploy to AWS, GCP and Azure (see our support matrix).
We are designing Wing to be familiar and friendly for developers who come from modern object-oriented background, so it will take you 5 minutes to learn.
Check out our getting started tutorial or hit the Wing Playground for an online experience.
In today’s issue
Wing 1.0 roadmap
We're excited to share our 1.0 roadmap, outlining our vision and the goals we aim to achieve in Wing 1.0.
Our mission with Wing is to empower developers to build cloud applications with an exceptional developer experience. To do this, we're focusing on establishing a stable foundation for the Wing programming language, defining essential cloud primitives, enabling the creation of libraries (winglibs) and custom platforms, and providing tools to simulate the cloud locally on your machine.
Building on the cloud shouldn’t be difficult, and we believe Wing can be a key part of the solution.
As we progress toward Wing 1.0, we'll be experimenting, learning, and making necessary adjustments. If you'd like to contribute or join us on this journey, we'd love to connect with you on GitHub or through our Discord server.
Language updates
To get the latest language updates you will need to update your wing version running the command below
npm install -g winglang
Internal access modifier
Wing now supports the internal
access modifier, which is particularly useful for library authors (winglib authors). This modifier allows you to make classes or methods accessible only within the module or library you’re developing, keeping them hidden from external consumers.
Previously, the only option if you were splitting definitions across multiple files was to make everything public, exposing all methods and classes to the library users. With internal
, you gain finer control over what parts of your code are exposed, ensuring that only what’s necessary is accessible.
This example shows a internal
class called OrderProcessingUtils
. As a library author you can call OrderProcessingUtils.calculateTax
within the module itself, but library consumers cannot (as it’s not exposed).
internal class OrderProcessingUtils {
static calculateTax(amount: num): num {
// Internal method to calculate tax
return amount * 0.1;
}
}
// OK inside the module we are building
let value = OrderProcessingUtils.calculateTax(10);
// Will not work if we try to use the code outside the module
let value = OrderProcessingUtils.calculateTax(10); // error
You can read more on our documentation about access modifiers.
New cloud resource cloud.Service
We have released the new cloud.Service
resource. The cloud.Service
class in Wing represents a cloud service with a defined lifecycle, including a start and an optional stop phase.
Example usage includes long-running processes like microservices or background data processing.
Cloud services will automatically start once deployed, you can opt out of this by specifying the autoStart
option.
bring cloud;
// inflight (runtime code) that is run within the service
let handler = inflight () => {
// Code is run on init/start of service
// This example we can start a custom HTTP server
log("Service started...");
let server = startHttpServer();
// Code is run when service stops
return () => {
log("Service stopped...");
// Example would be to stop the HTTP server
server.close();
};
};
// By default services are started when deployed
let autoStartService = new cloud.Service(handler);
// You can configure services not to start on deploy
let manualStartService = new cloud.Service(handler, autoStart: false);
Cloud services also have an inflight API that allows you to start or stop the service yourself, if you want more fine-grained control.
bring cloud;
let startCounter = new cloud.Counter() as "start counter";
let stopCounter = new cloud.Counter() as "stop counter";
let handler = inflight() => {
let i = startCounter.inc();
log("Service started for the ${i}th time...");
return () => {
let i = stopCounter.inc();
log("Service stopped for the ${i}th time...");
};
};
let service = new cloud.Service(handler, autoStart: false);
// Access service inflight API to start/stop the service in functions
new cloud.Function(inflight() => {
service.start();
assert(service.started());
}) as "start service";
new cloud.Function(inflight() => {
service.stop();
assert(!service.started());
}) as "stop service";
cloud.Service
currently supports the AWS platform (terraform and CDK), if you would like Azure or Google Cloud (GCP) support please comment and upvote the GitHub issues.
You can get started or read more in the documentation.
AWS Lambda Layer API for Wing
When compiling cloud.Function
resources to the AWS platform, AWS Lambda is used.
AWS Lambda supports lambda layers, which contain supplementary code or data for your Lambda functions. These can be useful for sharing library dependencies, a custom runtime or configuration files across your Lambda functions.
Wing now supports adding Lambda layers to cloud.Function
. To add a Lambda layer to your function, you can now use the aws.Function
class as shown below.
bring aws;
bring cloud;
// define your cloud function
let f = new cloud.Function(inflight () => {
log("Hello world!");
});
// attach lambda layer to the function
if let lambdaFn = aws.Function.from(f) {
// add your lambda layer
lambdaFn.addLambdaLayer("arn:aws:lambda:us-west-2:123456789012:layer:my-layer:1");
}
You can also attach Lambda layers to all your cloud functions by using a classe’s inflight method and the onLift hook. This allows you abstract and apply layers at a global level, ideal if you want to create winglibs for your developers.
bring aws;
bring cloud;
// Create Datadog class for wing application
class Datadog {
pub inflight fetchMetrics() {
// ...implementation...
}
// onLift hook, attach the lambda layer
pub onLift(host: std.IInflightHost, ops: Array<str>) {
if let lambdaFn = aws.Function.from(host) {
lambdaFn.addLambdaLayer("arn:aws:lambda:us-west-2:123456789012:layer:datadog-layer:1");
}
}
}
let d = new Datadog();
let api = new cloud.Api();
// Lambda layer is attached to inflight function
api.get("/metrics", inflight () => {
d.fetchMetrics();
});
If you want to learn more you can read the documentation.
Logging now supports more values
Logging now supports stringable values directly rather than wrapping them with quotes.
enum MyEnum { A, B, C }
let x = 5;
// before
log("{x}");
log("my string");
log("{42}");
log("{true}");
log("{Json { "cool": "beans" }}");
log("{MyEnum.A}");
// now
log(x);
log("my string");
log(42);
log(true);
log(Json { "cool": "beans" });
log(MyEnum.A);
Breaking changes
As we move towards Wing 1.0, we will be making changes along the way. Some of these changes may break existing code, but we will do our best to document these and keep you updated.
Goodbye elif, hello else if
To align with other imperative languages and improve the ease of picking up Wing we have removed elif and replaced it with else if
.
We recommend running a simple find and replacement over your codebase (like find . -type f -name "*.w" -exec perl -pi -e 's/\belif\b/else if/g' {} +
) to update to the new syntax.
let x: num = 11;
// before
if x <= 10 {
log("{x} is less than or equal to 10");
} elif x > 10 {
log("{x} is greater than 10");
}
// after
if x <= 10 {
log("{x} is less than or equal to 10");
} else if x > 10 {
log("{x} is greater than 10");
}
Read more in the pull request (https://github.com/winglang/wing/pull/6976)
ex.Table and ex.Redis are now winglibs
ex.Redis
and ex.Table
have not been removed from the standard library in favour of dedicated libraries. You can now use the winglibs for Redis, DynamoDB and Postgres.
@inflight intrinsic has been removed
Wing supports interoperating with TypeScript and JavaScript code, these methods were previously using externs
or @inflight
. The interoperating with TypeScript allows you to use TypeScript code within your Wing applications.
After using @inflight
and through user feedback we found a few DX issues with the intrinsic (read pull request for more information). For this reason we decided to remove the intrinsic and recommend developers to use the extern
method .
cloud.Function
now accepts Json
The input and return types for cloud.Function
has been changed from optional string (str?
) to optional JSON (Json?
) to align with event formats used by major cloud providers like AWS, GCP and Azure.
bring cloud;
// before
let x = new cloud.Function(inflight (payload: str?) => {
let data = Json.stringify(payload);
log(data);
});
// after
let x = new cloud.Function(inflight (payload: Json?) => {
log(Json.stringify(payload));
});
Additional breaking changes
- winglib
cdk8s
has been renamed tok8s
(https://github.com/winglang/winglibs/pull/298) .node
has been removed in favor ofnodeof()
- https://github.com/winglang/wing/pull/6721- Removed “Optional test” operator - https://github.com/winglang/wing/pull/6804
- change
cloud.Function
event type fromstr
toJson
- https://github.com/winglang/wing/pull/6219
Wing console updates
The Wing Console is a web application that is designed to enhance the developer experience when viewing, exploring and interacting with your Wing applications. The wing console provides instant feedback during cloud application development process.
New table component ui.Table
Wing allows developers to create their own resources. These resources are shown in the Wing console. Using the ui
standard library it’s possible to add custom components for interacting with your resources and displaying information, like Buttons, Fields, FileBrowsers and now Tables.
In this example we create a new Stripe
resource with a few public methods. When developers interact with this resource using the Wing console they can also see a list of customers in a table (using the ui.Table
resource and populating it with custom data).
Tables can be used to show any information represented by JSON into the wing console.
To learn more and get started you can read the documentation.
Nodes can now be collapsed and expanded
Nodes in the Wing console can now be expanded or collapsed, helping you navigate the map view in the Wing console.
You can try it out yourself in our playground.
Ability to filter logs in the Wing console
New filter capabilities have now been added to the console. This gives developers the ability to quickly filter logs within the Wing Console.
Winglibs
Wing libraries (winglibs) are packages you can import into your wing application. Anybody can create a winglib and add them to our eco system of libraries.
New wing packages
Here is a list of new wing packages that have been released
- @winglibs/momento - Use the Momento cache with Wing.
- @winglibs/slack - Integrate with Slack using Wing.
- @winglibs/ses - Interact with the AWS SES ervice
- @winglibs/sns - Interact with the AWS SNS service
Have an idea for a new winglib? Feel free to reach out to us on Discord or make a pull request on GitHub.
Summary
That’s it for this edition!
You are invited to join the Wing Discord! Come say hello and hang out with fellow Wingnuts! Give winglang.io a visit and take Wing out for a spin. If you're not already, stay updated on the latest changes in our repo.
Catch you next month!
- The Wing Team