Component Interface
This section describes how your Golem Component's public interface is defined using the WASM component model and how is it mapped into the Golem API.
The page is divided into two major sections by tiers, as the ability to define your component's interface is one of the primary differentiators between our different language tiers. Read the Building Components page for more information.
This page will use Golem CLI parameter names when talking about how to invoke functions, but the same rules apply when using the REST API too.
Tier 1 languages
Tier 1 languages use the WASM component model's tooling to define their interface using WIT files. Please read the official design document of the WIT format (opens in a new tab) to learn what it is capable of.
For each tier 1 language there is a binding generator tool that takes the WIT definition and generates the appropriate binding code in the given guest language. Read Building Components for more information about how these tools work.
The WIT definition is also embedded in the compiled WASM that you upload to Golem. This is how Golem knows what the exported functions are, and it can validate the provided parameters to make sure they have the correct type.
Function names
This section explains how you can map the exported function names from your WIT definition to fully qualified names to be passed in the --function
parameter when invoking an instance.
The component you define has a WIT package, specified in the top of your WIT definition.
For example if you generated your code using golem new
and did not specify a custom package name, it will be:
package golem:component
This package name can optionally specify a package version as well, such as:
package golem:component@0.3.2
You can have any other pair of names following the above syntax.
The WIT definition should contain a single world (otherwise the world to be used have to be specified for the tools used during compilation). The name of this world does not matter for Golem - it won't be part of the function's fully qualified name.
For example it can be:
world my-component-world {
// ...
}
In this world
you can either export
- one or more interface
- or one or more functions directly
The following example demonstrates both:
package golem:component;
interface api {
record product-item {
product-id: string,
name: string,
price: float32,
quantity: u32,
}
add-item: func(item: product-item) -> ();
remove-item: func(product-id: string) -> ();
}
world my-component-world {
export api;
export dump: func() -> result<string, string>;
}
The name of the interface(s) and function(s) are completely user defined, there are no rules to follow other than the syntax rules of WIT itself.
In the above example we have 3 exported functions and we can refer to them in the --function
parameter with the following fully qualified names, consisting of the package name and the exported path:
golem:component/api.{add-item}
golem:component/api.{remove-item}
golem:component.{dump}
Note that the syntax is the same as the one used for the use
statements in the WIT file.
Resources
WIT specifications also allow the definition of resources. These are constructed via special constructors, have methods, and can also have associated static functions. Golem supports exporting resources, enabling an alternative of having a separate worker for each entity. When exporting resources, a single worker may own an arbitrary number of instances of the exported resource, and the method invocations's first parameter must be the resource handle returned by the invoked constructor.
There is a special naming syntax provided by Golem that makes it more convenient to invoke resource constructors and methods. Take the following example:
package golem:component;
interface api {
resource counter {
constructor(name: string);
inc-by: func(value: u64);
get-value: func() -> u64;
merge-counters: static func(counter1: counter, counter2: counter, name: string) -> counter;
}
}
world my-world {
export api;
}
For this WIT specification, the following function names are valid when using Golem's invocation API or CLI:
golem:component/api.{counter.new}
- refers to the above defined constructorgolem:component/api.{counter.inc-by}
golem:component/api.{counter.get-value}
golem:component/api.{counter.merge-counters}
golem:component/api.{counter.drop}
- special function that drops the instance while the worker continues running
Implicit resource creation
With the above described naming conventions it is possible to manually create instances of resources, and then use the returned resource handle to invoke methods on them.
There is an easier way to work with resources in Golem, that assumes that a given resource instance is associated with the constructor parameters it is created with. This way it is possible to target a specific instance just by using the function name, and the resource instance will be automatically selected or created if it does not exist yet.
To use this feature, pass the target constructor parameters in the function name's resource name part in parentheses. For example, with the above defined counter
resource we can immediately create and a new counter and increment it by calling:
golem:component/api.{counter("my-counter").inc-by}
This will create a new counter instance with the name my-counter
and increment it. If the counter with the name my-counter
already exists, it will be used.
The syntax for passing inlined parameters to the constructor is using the WAVE syntax (opens in a new tab).
Parameters and results
This section defines the mapping from the different types you can use or define in your WIT definition and the JSON you pass to the --parameters
parameter of the invocation and see as your invocation's result.
When invoking a function, the JSON passed to --parameters
always has to be a JSON array. Each element of this array corresponds to one parameter of the function. So to call a function without any parameters pass an empty array ([]
). The result of a function invocation is also a JSON.
The following table maps types you can use in WIT to their JSON encoding:
WIT type | JSON type | Description |
---|---|---|
bool | JSON boolean | Primitive boolean type |
u8 | JSON number | Unsigned 8-bit integer |
s8 | JSON number | Signed 8-bit integer |
u16 | JSON number | Unsigned 16-bit integer |
s16 | JSON number | Signed 16-bit integer |
u32 | JSON number | Unsigned 32-bit integer |
s32 | JSON number | Signed 32-bit integer |
u64 | JSON number | Unsigned 64-bit integer |
s64 | JSON number | Signed 64-bit integer |
float32 | JSON number | 32-bit floating point number |
float64 | JSON number | 64-bit floating point number |
char | JSON number | ASCII character |
string | JSON string | String |
<t1, t2, ...> | JSON array of the items: [v1, v2, …] | Tuple of types t1, t2, … |
list<t> | JSON array of the items: [item1, item2, …] | List of items of type t |
option<t> | null if not defined the inner value if defined | An option of type t |
result<t, e> | Object with either an ok or an err field:{ "ok": ... } { "err": ... } If t or e is unit (_ in WIT) then use null in the JSON, for example { "ok": null } . | Type representing either a success of type t or a failure of type e |
handle | not supported yet | |
id | not supported yet | |
record | JSON object where for each record field there is a field with the same name. | Record containing a series of named fields. |
variant | JSON object with a single field that has the name of one of the variants. For example: { "child": 10 } | Variant that can be one of the specified types, discriminated by a case name. |
enum | JSON string holding the name of the enum, for example "low" | Enum is a set of possible named values |
flags | A JSON array of strings | Set of possible name values, where you can select more than one of them. |
handle | a JSON string that starts with the resource owner's worker uri, followed by a slash and a numeric resource id: "worker://component-id/worker-name/resource-id" | Points to a resource created on a given worker |
Tier 2 languages
For Tier 2 languages you cannot define more than one function to be exported. The function that Golem will run is your program's main function, without passing any arguments or getting any result values.
Function names
The function name for tier 2 languages that you need to pass to the --function
parameter of Golem CLI is always:
wasi:cli/run@0.2.0.{run}
Parameters and results
As you cannot define any parameter or result types in tier 2 the only option is to use the stdio mode or the stdio event loop mode.
This is enabled in the Golem CLI using the --use-stdio
command when invoking an instance.
Once it is enabled, the JSON you pass to the --parameters
parameter will be directly available to read from the worker's standard input, and Golem expects the run
function to write a result JSON to the standard output.
No further type checking is performed, but both the input and the output is expected to be JSONs.