Provides .NET 7.0 API/SPI and Model Validation for the Serverless Workflow Specification
With the SDK, you can:
- Read and write workflow JSON and YAML definitions
- Programmatically build workflow definitions
- Validate workflow definitions (both schema and DSL integrity validation)
Latest Releases | Conformance to spec version |
---|---|
0.8.7 | 0.8 |
dotnet nuget add package ServerlessWorkflow.Sdk
services.AddServerlessWorkflow();
var workflow = WorkflowDefinition.Create("MyWorkflow", "MyWorkflow", "1.0")
.StartsWith("inject", flow =>
flow.Inject(new { username = "test", password = "123456" }))
.Then("operation", flow =>
flow.Execute("fakeApiFunctionCall", action =>
{
action.Invoke(function =>
function.WithName("fakeFunction")
.SetOperationUri(new Uri("https://fake.com/swagger.json#fake")))
.WithArgument("username", "${ .username }")
.WithArgument("password", "${ .password }");
})
.Execute("fakeEventTrigger", action =>
{
action
.Consume(e =>
e.WithName("fakeEvent")
.WithSource(new Uri("https://fakesource.com"))
.WithType("fakeType"))
.ThenProduce(e =>
e.WithName("otherEvent")
.WithSource(new Uri("https://fakesource.com"))
.WithType("fakeType"));
}))
.End()
.Build();
var reader = WorkflowReader.Create();
using(Stream stream = File.OpenRead("myWorkflow.json"))
{
var definition = reader.Read(stream, WorkflowDefinitionFormat.Json);
}
var writer = WorkflowWriter.Create();
using(Stream stream = new MemoryStream())
{
writer.Write(workflow, stream);
stream.Flush();
stream.Position = 0;
using(StreamReader reader = new StreamReader(stream))
{
var yaml = reader.ReadToEnd();
Console.WriteLine(yaml);
Console.ReadLine();
}
}
var validator = serviceProvider.GetRequiredService<IValidator<WorkflowDefinition>>();
var validationResult = validator.Validate(myWorkflow);
The SDK allows extending the Serverless Workflow in two ways, possibly combined: via metadata and via extensions.
Workflow components that support metadata, such as WorkflowDefinition
or StateDefinition
, expose a metadata
property,
which is a dynamic name/value mapping of properties used to enrich the serverless workflow model with information beyond its core definitions.
It has the advantage of being an easy, cross-compatible way of declaring additional data, but lacks well-defined, well-documented schema of the data, thus loosing the ability to validate it without custom implementation.
Adding metadata to a workflow:
var workflow = new WorkflowBuilder()
...
.WithMetadata(new Dictionary<string, object>() { { "metadataPropertyName", metadataPropertyValue } })
...
.Build();
Resulting workflow:
id: sample-workflow
version: 1.0.0
specVersion: 0.8
metadata:
metadataPropertyName: metadataPropertyValue #added to the metadata property of supporting components
...
Users have the ability to define extensions, providing the ability to extend, override or replace parts of the Serverless Workflow schema.
To do so, you must first create a file containing the JsonSchema of your extension, then reference it in your workflow definition.
Schema of a sample extension that adds a new greet
functionType
:
JSON | YAML |
---|---|
{
"$defs": {
"functions": {
"definitions": {
"function": {
"type": "object",
"properties": {
"type": {
"type": "string",
"description": "Defines the function type. Is either `rest`, `asyncapi, `rpc`, `graphql`, `odata`, `expression` or `greet`. Default is `rest`",
"enum": [
"rest",
"asyncapi",
"rpc",
"graphql",
"odata",
"expression",
"custom",
"greet"
],
"default": "rest"
}
}
}
}
}
}
} |
'$defs':
functions:
definitions:
function:
type: object
properties:
type:
type: string
description: Defines the function type. Is either `rest`, `asyncapi, `rpc`,
`graphql`, `odata`, `expression` or `greet`. Default is `rest`
enum:
- rest
- asyncapi
- rpc
- graphql
- odata
- expression
- custom
- greet
default: rest |
The above example refers to /$defs/functions
, because upon validation the SDK bundles all the Serverless Workflow Specification's schemas into the $defs
property of a single schema.
*In this case, functions
is the extensionless name of the schema file we want to override (https://serverlessworkflow.io/schemas/latest/functions.json).
A Json Merge Patch is performed sequentially on the bundled schema with the defined extensions, in declaring order.
In this case, the above schema will patch the object defined at /functions/definitions/function
in file https://serverlessworkflow.io/schemas/latest/functions.json
Extending a workflow:
var workflow = new WorkflowBuilder()
.WithId("sample-extended")
.WithName("Sample Extended Workflow")
.WithVersion("1.0.0")
.UseSpecVersion(ServerlessWorkflowSpecVersion.V08)
.UseExtension("extensionId", new Uri("file://.../extensions/greet-function-type.json"))
.StartsWith("do-work", flow => flow.Execute("greet", action => action
.Invoke(function => function
.OfType("greet")
.WithName("greet")
.ForOperation("#"))))
.End()
.Build();
Adding extension properties:
var workflow = new WorkflowBuilder()
...
.WithExtensionProperty("extensionPropertyName", propertyValue } })
...
.Build();
Resulting workflow:
id: sample-workflow
version: 1.0.0
specVersion: 0.8
extensionPropertyName: propertyValue #added as top level property of extended component, as opposed to metadata
...