<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jarrod Overson</title>
    <description>The latest articles on DEV Community by Jarrod Overson (@jsoverson).</description>
    <link>https://dev.to/jsoverson</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F176898%2Fa0045512-87de-473f-94e7-1439dc4f112f.jpg</url>
      <title>DEV Community: Jarrod Overson</title>
      <link>https://dev.to/jsoverson</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jsoverson"/>
    <language>en</language>
    <item>
      <title>Async Streams in WebAssembly with WasmRS</title>
      <dc:creator>Jarrod Overson</dc:creator>
      <pubDate>Wed, 11 Jan 2023 18:32:15 +0000</pubDate>
      <link>https://dev.to/jsoverson/async-streams-in-webassembly-with-wasmrs-jem</link>
      <guid>https://dev.to/jsoverson/async-streams-in-webassembly-with-wasmrs-jem</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;TL;DR: WasmRS is an implementation of &lt;a href="https://rsocket.io" rel="noopener noreferrer"&gt;RSocket&lt;/a&gt; for WebAssembly giving you reactive, async streams in and out of WASM modules.&lt;br&gt;
&lt;a href="https://github.com/nanobus/iota" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; | &lt;a href="https://github.com/nanobus/iota/blob/main/docs/wasmrs.md" rel="noopener noreferrer"&gt;Protocol details&lt;/a&gt; | &lt;a href="https://github.com/nanobus/iota/tree/main/rust" rel="noopener noreferrer"&gt;Rust source&lt;/a&gt; | &lt;a href="https://github.com/nanobus/iota/tree/main/rust" rel="noopener noreferrer"&gt;Go source&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;WebAssembly has immense potential but it is hardly user-friendly. It's making &lt;a href="https://github.com/WebAssembly/component-model" rel="noopener noreferrer"&gt;strides&lt;/a&gt; but what we have to work with today is a slog. Baseline WebAssembly only works with integers and floating point values. Your typical "Hello world" is a cumbersome mess of reading raw memory and dealing with bytes. Once you figure out how to &lt;a href="https://wapc.io" rel="noopener noreferrer"&gt;transfer complex data structures&lt;/a&gt; and make calls in both directions, you are left high and dry if your application needs to do anything asynchronous. When you eventually rig together an async WebAssembly solution, you're stuck when dealing with big data without streams. After streams, you'll eventually need to solve for back pressure. After back press... well you get the point.&lt;/p&gt;

&lt;p&gt;And that's the story of how we got to WasmRS.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's WasmRS?
&lt;/h2&gt;

&lt;p&gt;WasmRS is an implementation of the RSocket protocol in WebAssembly with some reactive stream concepts thrown in for usability. With WasmRS you treat WebAssembly modules like tiny services you open bidirectional sockets into.&lt;/p&gt;

&lt;p&gt;WasmRS uses &lt;a href="https://rsocket.io" rel="noopener noreferrer"&gt;RSocket&lt;/a&gt; framing and aligns terminology where possible to keep it familiar. RSocket defines four request types the protocol can handle:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fire &amp;amp; Forget&lt;/strong&gt;: a request that is sent where the response is ignored.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RequestResponse&lt;/strong&gt;: an asynchronous request with a single payload returning a single payload.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RequestStream&lt;/strong&gt;: a request with a single payload that returns a stream of payloads.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RequestChannel&lt;/strong&gt;: a request that takes a stream that returns a stream.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you are interested in the protocol details, check out the &lt;a href="https://github.com/nanobus/iota/blob/main/docs/wasmrs.md" rel="noopener noreferrer"&gt;wasmRS protocol documentation here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do I use it?
&lt;/h2&gt;

&lt;p&gt;Using wasmRS directly is a bit like using WebAssembly directly. There's a lot of boilerplate and many esoteric details to get right before you get what you want. If you're the sort that likes those details, check out the &lt;a href="https://github.com/nanobus/iota/tree/main/rust/wasm/baseline" rel="noopener noreferrer"&gt;baseline Rust implementation&lt;/a&gt; in the repository. If you're like me, the details are great but getting started rapidly is more important.&lt;/p&gt;

&lt;p&gt;Luckily, we've got &lt;a href="https://github.com/apexlang/apex" rel="noopener noreferrer"&gt;&lt;code&gt;apex&lt;/code&gt;&lt;/a&gt; templates to get us going.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Apexlang is a &lt;a href="https://dev.to/jsoverson/apexlang-project-templates-with-code-generators-50jp"&gt;project template and code generation tool suite&lt;/a&gt; that automates much of the boilerplate and getting started headache for projects.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We can use the &lt;code&gt;apex&lt;/code&gt; CLI and the project templates in &lt;a href="https://github.com/nanobus/iota" rel="noopener noreferrer"&gt;nanobus/iota&lt;/a&gt; to whip up a new project with one line.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apex new git@github.com:nanobus/iota.git &lt;span class="nt"&gt;-p&lt;/span&gt; templates/rust example
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;apex new&lt;/code&gt; command is like &lt;code&gt;git clone&lt;/code&gt; plus templating. It makes kickstarting projects easy and keeps being useful with code generation you'll see below.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hello, World!
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Tip: This section bootstraps you into building with wasmRS. To get straight to streams, skip to the next section.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;example/&lt;/code&gt; directory we just created is filled with a handful of new files. Most are rust-specific but take special note of the &lt;code&gt;apex.axdl&lt;/code&gt; file. That's Apexlang and is what the &lt;code&gt;apex&lt;/code&gt; CLI uses to keep generating code and documentation during the life of your project.&lt;/p&gt;

&lt;p&gt;Edit the &lt;code&gt;apex.axdl&lt;/code&gt; to look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="err"&gt;namespace&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;"example"&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;MyApi&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;service&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Above, we define a service called &lt;code&gt;MyApi&lt;/code&gt; that has one action, &lt;code&gt;greet&lt;/code&gt;, that takes an argument and returns a string. The &lt;code&gt;target&lt;/code&gt; argument is who to greet.&lt;/p&gt;

&lt;p&gt;Now run &lt;code&gt;apex generate&lt;/code&gt; to automagically generate a bunch of new files.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Note: The project template includes a &lt;code&gt;justfile&lt;/code&gt;. The &lt;a href="https://github.com/casey/just" rel="noopener noreferrer"&gt;&lt;code&gt;just&lt;/code&gt;&lt;/a&gt; tool is a task runner modeled after the good parts of &lt;code&gt;make&lt;/code&gt;. If you have &lt;code&gt;just&lt;/code&gt; installed, you can run &lt;code&gt;apex generate&lt;/code&gt; with the task &lt;code&gt;just codegen&lt;/code&gt;&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;apex generate
INFO Writing file ./src/actions/my_api/greet.rs &lt;span class="o"&gt;(&lt;/span&gt;mode:644&lt;span class="o"&gt;)&lt;/span&gt;
INFO Writing file ./src/lib.rs &lt;span class="o"&gt;(&lt;/span&gt;mode:644&lt;span class="o"&gt;)&lt;/span&gt;
INFO Writing file ./src/error.rs &lt;span class="o"&gt;(&lt;/span&gt;mode:644&lt;span class="o"&gt;)&lt;/span&gt;
INFO Writing file ./src/actions/mod.rs &lt;span class="o"&gt;(&lt;/span&gt;mode:644&lt;span class="o"&gt;)&lt;/span&gt;
INFO Formatting file ./src/error.rs
INFO Formatting file ./src/lib.rs
INFO Formatting file ./src/actions/mod.rs
INFO Formatting file ./src/actions/my_api/greet.rs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These new files include wasmRS boilerplate, scaffolding, and samples to get you started quickly.&lt;/p&gt;

&lt;p&gt;The file &lt;code&gt;./src/actions/my_api/greet.rs&lt;/code&gt; contains a stub for our &lt;code&gt;greet&lt;/code&gt; action.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;my_api_service&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Inputs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Outputs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;todo!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Add implementation"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Turn our greeter into an appropriate 'Hello World!" by returning a string like below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;my_api_service&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Inputs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Outputs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, {}!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="py"&gt;.target&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And build!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cargo build &lt;span class="nt"&gt;--target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;wasm32-unknown-unknown
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'll find your new &lt;code&gt;.wasm&lt;/code&gt; file at &lt;code&gt;target/wasm32-unknown-unknown/release/example.wasm&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The included &lt;code&gt;justfile&lt;/code&gt; has a &lt;code&gt;build&lt;/code&gt; command that runs the &lt;code&gt;cargo&lt;/code&gt; step above and puts the built &lt;code&gt;.wasm&lt;/code&gt; files in a &lt;code&gt;build/&lt;/code&gt; directory. It also runs the &lt;code&gt;codegen&lt;/code&gt; task before building to ensure files are up-to-date.&lt;/p&gt;


&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;just build
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls &lt;/span&gt;build/
example.wasm
&lt;/code&gt;&lt;/pre&gt;

&lt;/blockquote&gt;

&lt;p&gt;We'll need a suitable runner to see our WebAssembly run on the command line. For that, we can use &lt;a href="https://github.com/nanobus/nanobus" rel="noopener noreferrer"&gt;&lt;code&gt;NanoBus&lt;/code&gt;&lt;/a&gt; or the &lt;code&gt;wasmrs-request&lt;/code&gt; binary.&lt;/p&gt;

&lt;h3&gt;
  
  
  Running our WebAssembly with &lt;code&gt;wasmrs-request&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;To use the &lt;code&gt;wasmrs-request&lt;/code&gt; tool, first install it with the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cargo &lt;span class="nb"&gt;install &lt;/span&gt;wasmrs-request
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wasmrs-request ./build/example.wasm example.MyApi greet &lt;span class="s1"&gt;'{"target":"World"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Hello, World!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Running our WebAssembly with NanoBus
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Info: NanoBus is a framework for wiring components like wasmRS modules together into applications. If you want to turn a module like this into a web service or CLI app, &lt;a href="https://github.com/nanobus/nanobus" rel="noopener noreferrer"&gt;check it out&lt;/a&gt;!&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To use NanoBus we need a configuration that points to our &lt;code&gt;.wasm&lt;/code&gt; file. Make an &lt;code&gt;iota.yaml&lt;/code&gt; that looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;example&lt;/span&gt;
&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;0.0.1&lt;/span&gt;
&lt;span class="na"&gt;main&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;target/wasm32-unknown-unknown/release/example.wasm&lt;/span&gt;
&lt;span class="c1"&gt;# Or, if you're using `just build`:&lt;/span&gt;
&lt;span class="c1"&gt;# main: build/example.wasm&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run &lt;code&gt;nanobus invoke&lt;/code&gt; with a piped payload to witness our Hello World executed in all its glory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'{"target":"World"}'&lt;/span&gt; | nanobus invoke iota.yaml example.MyApi::greet
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="s2"&gt;"Hello, World!"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Streams!
&lt;/h2&gt;

&lt;p&gt;Now that you're familiar with building wasmRS WebAssembly and running it with NanoBus or &lt;code&gt;wasmrs-request&lt;/code&gt;, let's get to streaming.&lt;/p&gt;

&lt;p&gt;Your system's command line is a great place to experiment. Every CLI process's input and output is a stream.&lt;/p&gt;

&lt;p&gt;Let's add a &lt;code&gt;reverse&lt;/code&gt; method to our API that takes a stream of &lt;code&gt;string&lt;/code&gt; and outputs a stream of &lt;code&gt;string&lt;/code&gt;. This will let us pipe a file to our action and see the contents reversed, ready to pipe to another CLI process.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="err"&gt;namespace&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;"example"&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;MyApi&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;service&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;reverse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run &lt;code&gt;apex generate&lt;/code&gt; (or &lt;code&gt;just codegen&lt;/code&gt;) to generate the new code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;apex generate
INFO Writing file ./src/actions/my_api/reverse.rs &lt;span class="o"&gt;(&lt;/span&gt;mode:644&lt;span class="o"&gt;)&lt;/span&gt;
INFO Writing file ./src/actions/mod.rs &lt;span class="o"&gt;(&lt;/span&gt;mode:644&lt;span class="o"&gt;)&lt;/span&gt;
INFO Formatting file ./src/actions/my_api/reverse.rs
INFO Formatting file ./src/actions/mod.rs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice how &lt;code&gt;apex&lt;/code&gt; intelligently rewrites only some files and doesn't clobber your existing action. Generated files that shouldn't be edited typically have a header or warning calling it out. You're safe to edit others.&lt;/p&gt;

&lt;p&gt;Our new stub looks a little different than the simple Request/Response stub above:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;my_api_service&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;reverse&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;FluxReceiver&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Inputs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PayloadError&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;outputs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Flux&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Outputs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PayloadError&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Flux&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Outputs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PayloadError&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;todo!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Add implementation"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;WasmRS uses terminology from &lt;a href="https://rsocket.io" rel="noopener noreferrer"&gt;RSocket&lt;/a&gt; and reactive-streams to stay consistent. A &lt;code&gt;Flux&lt;/code&gt; is like a rust &lt;code&gt;Stream&lt;/code&gt; mixed with a channel. You can push to it, pass it around, pipe one to another, and await values. A &lt;code&gt;FluxReceiver&lt;/code&gt; is a &lt;code&gt;Flux&lt;/code&gt; that you can only receive values from. It's like the receiving end of a channel implemented as a &lt;code&gt;Stream&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To work with our streams, we await values from our input stream and push to our output stream. This example reverses each line of the input and sends it to the output.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;my_api_service&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;reverse&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;FluxReceiver&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Inputs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PayloadError&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;outputs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Flux&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Outputs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PayloadError&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Flux&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Outputs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PayloadError&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="nf"&gt;.next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;outputs&lt;/span&gt;&lt;span class="nf"&gt;.send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="nf"&gt;.chars&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.rev&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.collect&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;outputs&lt;/span&gt;&lt;span class="nf"&gt;.error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;PayloadError&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;application_error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="nf"&gt;.to_string&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="n"&gt;outputs&lt;/span&gt;&lt;span class="nf"&gt;.complete&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;outputs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To build it, we can use the &lt;code&gt;justfile&lt;/code&gt; again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cargo build &lt;span class="nt"&gt;--release&lt;/span&gt; &lt;span class="nt"&gt;--target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;wasm32-unknown-unknown
&lt;span class="c"&gt;# or `just build`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To run it with &lt;code&gt;wasmrs-request&lt;/code&gt;, we use the same path and action arguments as above with the addition of the &lt;code&gt;--channel&lt;/code&gt; flag and piped input.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;Cargo.toml |  wasmrs-request &lt;span class="nt"&gt;--channel&lt;/span&gt; ./build/example.wasm example.MyApi reverse
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now anything you pipe to our &lt;code&gt;reverse&lt;/code&gt; action will come out reversed!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;]egakcap[
"elpmaxe" = eman
"0.1.0" = noisrev
"1202" = noitide

]bil[
]"bilydc"[ = epyt-etarc

]esaeler.eliforp[
"slobmys" = pirts
1 = stinu-negedoc
eslaf = gubed
eurt = otl
"z" = level-tpo
"troba" = cinap

]seicnedneped[
"2.0" = tseug-srmsaw
"0.1" = rorresiht
} ]"evired"[ = serutaef ,eslaf = serutaef-tluafed ,"1" = noisrev { = edres
"1.0" = tiart-cnysa
"0.82.0" = ajnijinim

]seicnedneped-ved[
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Streaming data is critical for large payloads. Dealing with an enormous file or an asynchronous stream of text would be difficult to impossible without streaming concepts. WasmRS lets you take WebAssembly to new levels.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where to go next?
&lt;/h2&gt;

&lt;p&gt;WasmRS is the protocol we're using for &lt;a href="https://github.com/nanobus/iota" rel="noopener noreferrer"&gt;&lt;code&gt;iota&lt;/code&gt;&lt;/a&gt; dependencies. Iotas are libraries, microservices, and WebAssembly modules that use a common protocol so they can be swapped out, integrated, composed, and tested without changing your application.&lt;/p&gt;

&lt;p&gt;WasmRS is independent, generic and un-opinionated. You can use wasmRS in your own projects, use the iota code generators and run iotas yourself, or use wasmRS in completely new ways. The iota implementation is our opinionated implementation. Take what you want and leave what you don't.&lt;/p&gt;

&lt;h2&gt;
  
  
  More links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/nanobus/iota/blob/main/docs/wasmrs.md" rel="noopener noreferrer"&gt;wasmRS spec&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nanobus/iota/blob/main/docs/iota-spec.md" rel="noopener noreferrer"&gt;More on Iotas&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nanobus/iota/" rel="noopener noreferrer"&gt;GitHub Repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://nanobus.io" rel="noopener noreferrer"&gt;NanoBus&lt;/a&gt; (&lt;a href="https://github.com/nanobus/nanobus" rel="noopener noreferrer"&gt;github.com/nanobus/nanobus&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://apexlang.io" rel="noopener noreferrer"&gt;Apexlang&lt;/a&gt; (&lt;a href="https://github.com/apexlang/apex" rel="noopener noreferrer"&gt;github.com/apexlang/apex&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://discord.gg/candle" rel="noopener noreferrer"&gt;Candle Discord server&lt;/a&gt; to talk about WebAssembly, wasmRS, Apexlang, NanoBus, Rust, Go, Deno, TypeScript, and all the cool things.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Attribution
&lt;/h2&gt;

&lt;p&gt;Photo by Jason Pischke on &lt;a href="https://unsplash.com/photos/QirzSBYVH64?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditShareLink" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>gratitude</category>
    </item>
    <item>
      <title>Apexlang: Project Templates &amp; Code Generation</title>
      <dc:creator>Jarrod Overson</dc:creator>
      <pubDate>Fri, 06 Jan 2023 18:02:14 +0000</pubDate>
      <link>https://dev.to/jsoverson/apexlang-project-templates-with-code-generators-50jp</link>
      <guid>https://dev.to/jsoverson/apexlang-project-templates-with-code-generators-50jp</guid>
      <description>&lt;blockquote&gt;
&lt;h3&gt;
  
  
  TL;DR:
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;apex&lt;/code&gt; CLI let you create projects from templates and the Apexlang IDL lets you generate code, documentation, schemas, and more from a single source. Quick links: &lt;a href="//github.com/apexlang/apex"&gt;Github Repo&lt;/a&gt; &amp;amp; &lt;a href="https://apexlang.io/" rel="noopener noreferrer"&gt;apexlang.io homepage&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;How often do you start projects the same way? With the same boilerplate, same dependencies, same configuration, same everything? If you’re like me, you get your settings dialed in and reuse them in a base project template repeatedly. Eventually you might find yourself creating &lt;a href="https://github.com/jsoverson/typescript-boilerplate" rel="noopener noreferrer"&gt;git repos&lt;/a&gt; or &lt;a href="https://twitter.com/jsoverson/status/1097881605824237569" rel="noopener noreferrer"&gt;scripts&lt;/a&gt; to make this process buttery smooth.&lt;/p&gt;

&lt;p&gt;Tools like &lt;a href="https://yeoman.io/" rel="noopener noreferrer"&gt;&lt;code&gt;yeoman&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://github.com/Rich-Harris/degit" rel="noopener noreferrer"&gt;&lt;code&gt;degit&lt;/code&gt;&lt;/a&gt;, and &lt;a href="https://github.com/cargo-generate/cargo-generate" rel="noopener noreferrer"&gt;&lt;code&gt;cargo&lt;/code&gt;&lt;/a&gt; generate kept me happy for years. They add basic templating capabilities to the standard &lt;code&gt;git clone&lt;/code&gt; but they stop there. You’ll be hard pressed to find tools that go beyond setting up a directory structure.&lt;/p&gt;

&lt;p&gt;That’s where &lt;a href="https://apexlang.io" rel="noopener noreferrer"&gt;Apexlang&lt;/a&gt; comes in. Apexlang is a code generation and templating tool suite. It started as an interface definition language (IDL) for WebAssembly called WIDL but was too useful to be hidden away. It now contains the base functionality of tools like &lt;code&gt;degit&lt;/code&gt; combined with the code generation capability of tools like &lt;code&gt;protoc&lt;/code&gt; and &lt;code&gt;smithy&lt;/code&gt;. And unlike tools like &lt;code&gt;protoc&lt;/code&gt; and &lt;code&gt;smithy&lt;/code&gt;, code generators are written in TypeScript and are easier to get started with.&lt;/p&gt;

&lt;p&gt;With Apexlang you get your boilerplate along with code, documentation, schemas, and more all generated automatically, continuously, and easily.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check it out
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;apex new git@github.com:apexlang/codegen.git &lt;span class="nt"&gt;-p&lt;/span&gt; templates/nodejs my-project
Cloning into &lt;span class="s1"&gt;'/var/folders/pg/h7s94pd90w54hcbjpkvm58240000gn/T/77f11564'&lt;/span&gt;...
remote: Enumerating objects: 256, &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
remote: Counting objects: 100% &lt;span class="o"&gt;(&lt;/span&gt;256/256&lt;span class="o"&gt;)&lt;/span&gt;, &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
remote: Compressing objects: 100% &lt;span class="o"&gt;(&lt;/span&gt;210/210&lt;span class="o"&gt;)&lt;/span&gt;, &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
remote: Total 256 &lt;span class="o"&gt;(&lt;/span&gt;delta 54&lt;span class="o"&gt;)&lt;/span&gt;, reused 135 &lt;span class="o"&gt;(&lt;/span&gt;delta 18&lt;span class="o"&gt;)&lt;/span&gt;, pack-reused 0
Receiving objects: 100% &lt;span class="o"&gt;(&lt;/span&gt;256/256&lt;span class="o"&gt;)&lt;/span&gt;, 150.38 KiB | 6.27 MiB/s, &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
Resolving deltas: 100% &lt;span class="o"&gt;(&lt;/span&gt;54/54&lt;span class="o"&gt;)&lt;/span&gt;, &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
 ? Please enter the project description ›
INFO Writing file my-project/package.json &lt;span class="o"&gt;(&lt;/span&gt;mode:100644&lt;span class="o"&gt;)&lt;/span&gt;
INFO Writing file my-project/apex.yaml &lt;span class="o"&gt;(&lt;/span&gt;mode:100644&lt;span class="o"&gt;)&lt;/span&gt;
INFO Writing file my-project/apex.axdl &lt;span class="o"&gt;(&lt;/span&gt;mode:100644&lt;span class="o"&gt;)&lt;/span&gt;
INFO Writing file my-project/.gitignore &lt;span class="o"&gt;(&lt;/span&gt;mode:100644&lt;span class="o"&gt;)&lt;/span&gt;
INFO Writing file my-project/tsconfig.json &lt;span class="o"&gt;(&lt;/span&gt;mode:100644&lt;span class="o"&gt;)&lt;/span&gt;
INFO Writing file my-project/.vscode/settings.json &lt;span class="o"&gt;(&lt;/span&gt;mode:100644&lt;span class="o"&gt;)&lt;/span&gt;
INFO Writing file my-project/.vscode/tasks.json &lt;span class="o"&gt;(&lt;/span&gt;mode:100644
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;apex new&lt;/code&gt; command clones a repository to use as a template. The &lt;code&gt;-p&lt;/code&gt; option above tells apex to use a sub-directory and you can use &lt;code&gt;-b&lt;/code&gt; to specify a branch if necessary. The final argument is the directory to create.&lt;/p&gt;

&lt;p&gt;The template itself has configuration defined in .template files like &lt;a href="https://github.com/apexlang/codegen/blob/main/templates/nodejs/.template" rel="noopener noreferrer"&gt;this one&lt;/a&gt;. Any file &lt;code&gt;apex&lt;/code&gt; finds with a &lt;code&gt;.tmpl&lt;/code&gt; extension is treated as a text file to render with data defined in the &lt;code&gt;.template&lt;/code&gt; configuration along with user or environment variables.&lt;/p&gt;

&lt;p&gt;Cloning projects and rendering templates is useful, but it's the tip of the iceberg.&lt;/p&gt;

&lt;p&gt;The example above is a bare-bones TypeScript &amp;amp; node.js template. It includes an &lt;code&gt;apex.axdl&lt;/code&gt; definition and an &lt;code&gt;apex.yaml&lt;/code&gt; configuration file. These files are what drives &lt;code&gt;apex&lt;/code&gt; after the initial project creation.&lt;/p&gt;

&lt;p&gt;This templates' yaml configuration is simple. It points to the Apexlang definition file (an &lt;code&gt;.axdl&lt;/code&gt; file) and specifies the code generator plugin to use.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apex.axdl&lt;/span&gt;
&lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;https://raw.githubusercontent.com/apexlang/codegen/main/src/typescript/plugin.ts'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Plugins dynamically generate further configuration based on the Apexlang definition. Yeah, &lt;code&gt;apex&lt;/code&gt; uses Apexlang to configure &lt;code&gt;apex&lt;/code&gt; configuration.&lt;/p&gt;

&lt;p&gt;Plugins are TypeScript files that export a single function. The function takes in the current config along with an Apexlang spec, and spits out a new configuration.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;axdl&lt;/code&gt; file is where the magic is defined. It’s an interface definition language that looks a lot like GraphQL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="err"&gt;namespace&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;"greeting.v1"&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Greeter&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;sayHello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It models the parts you need to describe most APIs for languages and services.&lt;/p&gt;

&lt;p&gt;With a configuration and an &lt;code&gt;.axdl&lt;/code&gt; file, we can start generating code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;apex generate
INFO Writing file ./src/api.ts &lt;span class="o"&gt;(&lt;/span&gt;mode:644&lt;span class="o"&gt;)&lt;/span&gt;
INFO Writing file ./src/interfaces.ts &lt;span class="o"&gt;(&lt;/span&gt;mode:644&lt;span class="o"&gt;)&lt;/span&gt;
apex generate creates two newfiles, api.ts and interfaces.ts.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;src/interfaces.ts&lt;/code&gt; illustrates how &lt;code&gt;apex&lt;/code&gt; translates Apexlang types to TypeScript code. Apexlang interfaces become TypeScript interfaces and Apexlang types become TypeScript classes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Greeter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;sayHello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;firstName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;lastName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;
  &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In &lt;code&gt;src/api.ts&lt;/code&gt;, we get a boilerplate implementation of our interfaces that we can fill out with business logic. All the imports are handled for you and &lt;code&gt;apex&lt;/code&gt; leaves you ready to start coding.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Greeter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./interfaces&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GreeterImpl&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;Greeter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;sayHello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can also add documentation to our &lt;code&gt;.axdl&lt;/code&gt; file and it will render as comments in the code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="err"&gt;namespace&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;"greeting.v1"&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="err"&gt;"A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;simple&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;greeting&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;service"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Greeter&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="n"&gt;Say&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;sayHello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;"An&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;instance&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;person"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="n"&gt;The&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;person&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="n"&gt;The&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;person&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;apex&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;generate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;now&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;produces&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;this:&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;simple&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;greeting&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;service&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Greeter&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Say&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;sayHello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;An&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;instance&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;person&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Person&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;The&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;person&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;The&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;person&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;[&lt;/span&gt;&lt;span class="n"&gt;rest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;snipped&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="err"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  More generators!
&lt;/h2&gt;

&lt;p&gt;Writing what looks like code to generate a single instance of other code isn’t that exciting. You could have written the TypeScript by hand. But &lt;code&gt;apex&lt;/code&gt; is more than just a code generator. It’s a code generation framework. It’s a templating framework. It’s a documentation framework. It’s a schema framework. It’s a configuration framework. It’s a framework for frameworks.&lt;/p&gt;

&lt;p&gt;We can just as easily generate markdown documentation for our API by adding in a custom generates section. (These are what plugins generate for you but you can add your own manually.)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;generates&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;API.md&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;module&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://deno.land/x/apex_codegen/markdown/mod.ts&lt;/span&gt;
    &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;My&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Awesome&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Project'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The generates block is keyed with the file to be generated (i.e. &lt;code&gt;API.md&lt;/code&gt;) and the generator configuration. In this case we're delegating to the markdown module of the official &lt;a href="https://github.com/apexlang/codegen" rel="noopener noreferrer"&gt;Apexlang codegen&lt;/a&gt; project.&lt;/p&gt;

&lt;p&gt;This is the markdown we generate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# My Awesome Project&lt;/span&gt;

Namespace: &lt;span class="gs"&gt;**`greeting.v1`**&lt;/span&gt;

&lt;span class="gu"&gt;## Interfaces&lt;/span&gt;

&lt;span class="gu"&gt;### **Greeter**&lt;/span&gt;

A simple greeting service
&lt;span class="p"&gt;
-&lt;/span&gt; &lt;span class="gs"&gt;**`sayHello(to: Person) -&amp;gt; string`**&lt;/span&gt;: Say hello to a Person

&lt;span class="gu"&gt;## Types&lt;/span&gt;

&lt;span class="gu"&gt;### **Person**&lt;/span&gt;

An instance of a person
&lt;span class="p"&gt;
-&lt;/span&gt; &lt;span class="gs"&gt;**`firstName: string`**&lt;/span&gt; : The person's first name
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**`lastName: string`**&lt;/span&gt; : The person's last name
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are generators for C#, Go, TinyGo, Rust, Java, Protobuf, OpenAPI, JSONSchema, Python, &lt;a href="https://github.com/apexlang/codegen/tree/main/src" rel="noopener noreferrer"&gt;and more&lt;/a&gt;. If you work in shops with many teams and languages, you must look into Apexlang. It’s a game changer. Specify your interfaces once and generate scaffolding, boilerplate, documentation, bindings, everything from there. You can inherit from the existing Apexlang generators or create entirely new ones. It’s just TypeScript running on Deno and you can host your templates and generators anywhere.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s next?
&lt;/h2&gt;

&lt;p&gt;I didn’t start Apexlang but I recognized the value immediately when using it as WIDL. The original author (Phil Kedy) and I have joined up as part of &lt;a href="https://candle.dev/" rel="noopener noreferrer"&gt;Candle&lt;/a&gt; to build tools that make everything about software easier. Once you start it’s hard to stop. We use Apexlang heavily on &lt;a href="http://github.com/nanobus/nanobus" rel="noopener noreferrer"&gt;NanoBus&lt;/a&gt;, our WebAssembly-oriented developer platform.&lt;/p&gt;

&lt;p&gt;We’re in the process of fully converting Apexlang and its dependencies from a go/node hybrid to deno and WebAssembly. The apex CLI, parsers, and code generators are now fully deno but there may be some rough edges as we iron out the wrinkles.&lt;/p&gt;

&lt;p&gt;We hang out in &lt;a href="https://jsoverson.medium.com/discord.gg/candle" rel="noopener noreferrer"&gt;our discord server&lt;/a&gt; and are always happy to chat about Apexlang, WebAssembly, go, rust, or anything else. Come say hi!&lt;/p&gt;

</description>
      <category>linux</category>
    </item>
  </channel>
</rss>
