UNPKG

signalk-server

Version:

An implementation of a [Signal K](http://signalk.org) server for boats.

199 lines (173 loc) 66.7 kB
<!DOCTYPE html><html class="default" lang="en" data-base="../../../"><head><meta charset="utf-8"/><meta http-equiv="x-ua-compatible" content="IE=edge"/><title>AssemblyScript Plugins | Signal K</title><meta name="description" content="Documentation for Signal K"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="../../../assets/style.css?cache=1783009712609"/><link rel="stylesheet" href="../../../assets/highlight.css?cache=1783009712609"/><script defer src="../../../assets/main.js?cache=1783009712609"></script><script async src="../../../assets/icons.js?cache=1783009712609" id="tsd-icons-script"></script><script async src="../../../assets/search.js?cache=1783009712609" id="tsd-search-script"></script><script async src="../../../assets/navigation.js?cache=1783009712609" id="tsd-nav-script"></script><script async src="../../../assets/hierarchy.js?cache=1783009712609" id="tsd-hierarchy-script"></script><link rel="stylesheet" href="../../../assets/theme.css"/><script>if(window.self!==window.top){document.documentElement.classList.add('embedded')}</script></head><body><script>document.documentElement.dataset.theme = localStorage.getItem("tsd-theme") || "os";document.body.style.display="none";setTimeout(() => window.app?app.showPage():document.body.style.removeProperty("display"),500)</script><header class="tsd-page-toolbar"><div class="tsd-toolbar-contents container"><a href="../../../index.html" class="title"><img class="title-logo" src="../../../assets/logo.svg" alt="Signal K"/><svg class="title-home-icon" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-label="Documentation home"><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path><polyline points="9 22 9 12 15 12 15 22"></polyline></svg></a><button id="tsd-search-trigger" class="tsd-widget" aria-label="Search"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../../../assets/icons.svg#icon-search"></use></svg><span class="visible@s">Search</span></button><dialog id="tsd-search" aria-label="Search"><input role="combobox" id="tsd-search-input" aria-controls="tsd-search-results" aria-autocomplete="list" aria-expanded="true" autocapitalize="off" autocomplete="off" placeholder="Search the docs" maxLength="100"/><ul role="listbox" id="tsd-search-results"></ul><div id="tsd-search-status" aria-live="polite" aria-atomic="true"><div>Preparing search index...</div></div></dialog><div id="tsd-toolbar-links"><a href="https://discord.gg/uuZrwz4dCS" target="_blank" rel="noopener" class="toolbar-icon visible@s" aria-label="Discord"><svg width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><path d="M524.5 69.8a1.5 1.5 0 0 0 -.8-.7A485.1 485.1 0 0 0 404.1 32a1.8 1.8 0 0 0 -1.9 .9 337.5 337.5 0 0 0 -14.9 30.6 447.8 447.8 0 0 0 -134.4 0 309.5 309.5 0 0 0 -15.1-30.6 1.9 1.9 0 0 0 -1.9-.9A483.7 483.7 0 0 0 116.1 69.1a1.7 1.7 0 0 0 -.8 .7C39.1 183.7 18.2 294.7 28.4 404.4a2 2 0 0 0 .8 1.4A487.7 487.7 0 0 0 176 479.9a1.9 1.9 0 0 0 2.1-.7A348.2 348.2 0 0 0 208.1 430.4a1.9 1.9 0 0 0 -1-2.6 321.2 321.2 0 0 1 -45.9-21.9 1.9 1.9 0 0 1 -.2-3.1c3.1-2.3 6.2-4.7 9.1-7.1a1.8 1.8 0 0 1 1.9-.3c96.2 43.9 200.4 43.9 295.5 0a1.8 1.8 0 0 1 1.9 .2c2.9 2.4 6 4.9 9.1 7.2a1.9 1.9 0 0 1 -.2 3.1 301.4 301.4 0 0 1 -45.9 21.8 1.9 1.9 0 0 0 -1 2.6 391.1 391.1 0 0 0 30 48.8 1.9 1.9 0 0 0 2.1 .7A486 486 0 0 0 610.7 405.7a1.9 1.9 0 0 0 .8-1.4C623.7 277.6 590.9 167.5 524.5 69.8zM222.5 337.6c-29 0-52.8-26.6-52.8-59.2S193.1 219.1 222.5 219.1c29.7 0 53.3 26.8 52.8 59.2C275.3 311 251.9 337.6 222.5 337.6zm195.4 0c-29 0-52.8-26.6-52.8-59.2S388.4 219.1 417.9 219.1c29.7 0 53.3 26.8 52.8 59.2C470.7 311 447.5 337.6 417.9 337.6z"></path></svg></a><a href="https://github.com/SignalK/signalk-server" target="_blank" rel="noopener" class="toolbar-icon visible@s" aria-label="Discord"><svg width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3 .3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5 .3-6.2 2.3zm44.2-1.7c-2.9 .7-4.9 2.6-4.6 4.9 .3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3 .7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3 .3 2.9 2.3 3.9 1.6 1 3.6 .7 4.3-.7 .7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3 .7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3 .7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"></path></svg></a><a href="#" class="tsd-widget menu" id="tsd-toolbar-menu-trigger" data-toggle="menu" aria-label="Menu"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../../../assets/icons.svg#icon-menu"></use></svg></a></div></div></header><div class="container container-main"><div class="col-content"><div class="tsd-page-title"><ul class="tsd-breadcrumb" aria-label="Breadcrumb"><li><a href="../../../Developing.html">Developing</a></li><li><a href="../../Plugins.html">Plugins</a></li><li><a href="../WASM_Plugins.html">WASM Plugins</a></li><li><a href="" aria-current="page">AssemblyScript Plugins</a></li></ul></div><div class="tsd-panel tsd-typography"><h1 id="creating-assemblyscript-plugins" class="tsd-anchor-link">Creating AssemblyScript Plugins<a href="#creating-assemblyscript-plugins" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../../../assets/icons.svg#icon-anchor"></use></svg></a></h1> <p>AssemblyScript is the recommended language for developers familiar with TypeScript. It produces the smallest binaries (3-10 KB) and has the fastest development cycle.</p> <h2 id="step-1-install-sdk" class="tsd-anchor-link">Step 1: Install SDK<a href="#step-1-install-sdk" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../../../assets/icons.svg#icon-anchor"></use></svg></a></h2> <pre><code class="bash"><span class="hl-5">npm</span><span class="hl-0"> </span><span class="hl-4">install</span><span class="hl-0"> </span><span class="hl-4">@signalk/assemblyscript-plugin-sdk</span><br/><span class="hl-5">npm</span><span class="hl-0"> </span><span class="hl-4">install</span><span class="hl-0"> </span><span class="hl-2">--save-dev</span><span class="hl-0"> </span><span class="hl-4">assemblyscript</span> </code><button type="button">Copy</button></pre> <h2 id="step-2-create-plugin-file" class="tsd-anchor-link">Step 2: Create Plugin File<a href="#step-2-create-plugin-file" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../../../assets/icons.svg#icon-anchor"></use></svg></a></h2> <p>Create <code>assembly/index.ts</code>:</p> <pre><code class="typescript"><span class="hl-1">import</span><span class="hl-0"> {</span><br/><span class="hl-0"> Plugin,</span><br/><span class="hl-0"> Delta,</span><br/><span class="hl-0"> Update,</span><br/><span class="hl-0"> PathValue,</span><br/><span class="hl-0"> emit,</span><br/><span class="hl-0"> setStatus</span><br/><span class="hl-0">} </span><span class="hl-1">from</span><span class="hl-0"> </span><span class="hl-4">&#39;@signalk/assemblyscript-plugin-sdk/assembly&#39;</span><br/><br/><span class="hl-1">class</span><span class="hl-0"> </span><span class="hl-5">MyPlugin</span><span class="hl-0"> </span><span class="hl-1">extends</span><span class="hl-0"> </span><span class="hl-2">Plugin</span><span class="hl-0"> {</span><br/><span class="hl-0"> </span><span class="hl-7">name</span><span class="hl-0">()</span><span class="hl-1">:</span><span class="hl-0"> </span><span class="hl-2">string</span><span class="hl-0"> {</span><br/><span class="hl-0"> </span><span class="hl-1">return</span><span class="hl-0"> </span><span class="hl-4">&#39;My AssemblyScript Plugin&#39;</span><br/><span class="hl-0"> }</span><br/><br/><span class="hl-0"> </span><span class="hl-7">schema</span><span class="hl-0">()</span><span class="hl-1">:</span><span class="hl-0"> </span><span class="hl-2">string</span><span class="hl-0"> {</span><br/><span class="hl-0"> </span><span class="hl-1">return</span><span class="hl-0"> </span><span class="hl-4">`{</span><br/><span class="hl-4"> &quot;type&quot;: &quot;object&quot;,</span><br/><span class="hl-4"> &quot;properties&quot;: {</span><br/><span class="hl-4"> &quot;updateRate&quot;: {</span><br/><span class="hl-4"> &quot;type&quot;: &quot;number&quot;,</span><br/><span class="hl-4"> &quot;default&quot;: 1000</span><br/><span class="hl-4"> }</span><br/><span class="hl-4"> }</span><br/><span class="hl-4"> }`</span><br/><span class="hl-0"> }</span><br/><br/><span class="hl-0"> </span><span class="hl-7">start</span><span class="hl-0">(</span><span class="hl-5">config</span><span class="hl-1">:</span><span class="hl-0"> </span><span class="hl-2">string</span><span class="hl-0">)</span><span class="hl-1">:</span><span class="hl-0"> </span><span class="hl-5">i32</span><span class="hl-0"> {</span><br/><span class="hl-0"> </span><span class="hl-7">setStatus</span><span class="hl-0">(</span><span class="hl-4">&#39;Started&#39;</span><span class="hl-0">)</span><br/><br/><span class="hl-0"> </span><span class="hl-6">// Emit a test delta</span><br/><span class="hl-0"> </span><span class="hl-1">const</span><span class="hl-0"> </span><span class="hl-2">pathValue</span><span class="hl-0"> </span><span class="hl-1">=</span><span class="hl-0"> </span><span class="hl-1">new</span><span class="hl-0"> </span><span class="hl-7">PathValue</span><span class="hl-0">(</span><span class="hl-4">&#39;test.value&#39;</span><span class="hl-0">, </span><span class="hl-4">&#39;&quot;hello&quot;&#39;</span><span class="hl-0">)</span><br/><span class="hl-0"> </span><span class="hl-1">const</span><span class="hl-0"> </span><span class="hl-2">update</span><span class="hl-0"> </span><span class="hl-1">=</span><span class="hl-0"> </span><span class="hl-1">new</span><span class="hl-0"> </span><span class="hl-7">Update</span><span class="hl-0">([pathValue])</span><br/><span class="hl-0"> </span><span class="hl-1">const</span><span class="hl-0"> </span><span class="hl-2">delta</span><span class="hl-0"> </span><span class="hl-1">=</span><span class="hl-0"> </span><span class="hl-1">new</span><span class="hl-0"> </span><span class="hl-7">Delta</span><span class="hl-0">(</span><span class="hl-4">&#39;vessels.self&#39;</span><span class="hl-0">, [update])</span><br/><span class="hl-0"> </span><span class="hl-7">emit</span><span class="hl-0">(delta)</span><br/><br/><span class="hl-0"> </span><span class="hl-1">return</span><span class="hl-0"> </span><span class="hl-2">0</span><span class="hl-0"> </span><span class="hl-6">// Success</span><br/><span class="hl-0"> }</span><br/><br/><span class="hl-0"> </span><span class="hl-7">stop</span><span class="hl-0">()</span><span class="hl-1">:</span><span class="hl-0"> </span><span class="hl-5">i32</span><span class="hl-0"> {</span><br/><span class="hl-0"> </span><span class="hl-7">setStatus</span><span class="hl-0">(</span><span class="hl-4">&#39;Stopped&#39;</span><span class="hl-0">)</span><br/><span class="hl-0"> </span><span class="hl-1">return</span><span class="hl-0"> </span><span class="hl-2">0</span><br/><span class="hl-0"> }</span><br/><span class="hl-0">}</span><br/><br/><span class="hl-6">// Export for Signal K</span><br/><span class="hl-1">const</span><span class="hl-0"> </span><span class="hl-2">plugin</span><span class="hl-0"> </span><span class="hl-1">=</span><span class="hl-0"> </span><span class="hl-1">new</span><span class="hl-0"> </span><span class="hl-7">MyPlugin</span><span class="hl-0">()</span><br/><span class="hl-1">export</span><span class="hl-0"> </span><span class="hl-1">function</span><span class="hl-0"> </span><span class="hl-7">plugin_name</span><span class="hl-0">()</span><span class="hl-1">:</span><span class="hl-0"> </span><span class="hl-2">string</span><span class="hl-0"> {</span><br/><span class="hl-0"> </span><span class="hl-1">return</span><span class="hl-0"> plugin.</span><span class="hl-7">name</span><span class="hl-0">()</span><br/><span class="hl-0">}</span><br/><span class="hl-1">export</span><span class="hl-0"> </span><span class="hl-1">function</span><span class="hl-0"> </span><span class="hl-7">plugin_schema</span><span class="hl-0">()</span><span class="hl-1">:</span><span class="hl-0"> </span><span class="hl-2">string</span><span class="hl-0"> {</span><br/><span class="hl-0"> </span><span class="hl-1">return</span><span class="hl-0"> plugin.</span><span class="hl-7">schema</span><span class="hl-0">()</span><br/><span class="hl-0">}</span><br/><span class="hl-1">export</span><span class="hl-0"> </span><span class="hl-1">function</span><span class="hl-0"> </span><span class="hl-7">plugin_start</span><span class="hl-0">(</span><span class="hl-5">configPtr</span><span class="hl-1">:</span><span class="hl-0"> </span><span class="hl-5">usize</span><span class="hl-0">, </span><span class="hl-5">configLen</span><span class="hl-1">:</span><span class="hl-0"> </span><span class="hl-5">usize</span><span class="hl-0">)</span><span class="hl-1">:</span><span class="hl-0"> </span><span class="hl-5">i32</span><span class="hl-0"> {</span><br/><span class="hl-0"> </span><span class="hl-1">const</span><span class="hl-0"> </span><span class="hl-2">configBytes</span><span class="hl-0"> </span><span class="hl-1">=</span><span class="hl-0"> </span><span class="hl-1">new</span><span class="hl-0"> </span><span class="hl-7">Uint8Array</span><span class="hl-0">(configLen)</span><br/><span class="hl-0"> </span><span class="hl-1">for</span><span class="hl-0"> (</span><span class="hl-1">let</span><span class="hl-0"> i </span><span class="hl-1">=</span><span class="hl-0"> </span><span class="hl-2">0</span><span class="hl-0">; i </span><span class="hl-1">&lt;</span><span class="hl-0"> configLen; i</span><span class="hl-1">++</span><span class="hl-0">) {</span><br/><span class="hl-0"> configBytes[i] </span><span class="hl-1">=</span><span class="hl-0"> </span><span class="hl-7">load</span><span class="hl-0">&lt;</span><span class="hl-5">u8</span><span class="hl-0">&gt;(configPtr </span><span class="hl-1">+</span><span class="hl-0"> i)</span><br/><span class="hl-0"> }</span><br/><span class="hl-0"> </span><span class="hl-1">const</span><span class="hl-0"> </span><span class="hl-2">configJson</span><span class="hl-0"> </span><span class="hl-1">=</span><span class="hl-0"> String.</span><span class="hl-2">UTF8</span><span class="hl-0">.</span><span class="hl-7">decode</span><span class="hl-0">(configBytes.buffer)</span><br/><span class="hl-0"> </span><span class="hl-1">return</span><span class="hl-0"> plugin.</span><span class="hl-7">start</span><span class="hl-0">(configJson)</span><br/><span class="hl-0">}</span><br/><span class="hl-1">export</span><span class="hl-0"> </span><span class="hl-1">function</span><span class="hl-0"> </span><span class="hl-7">plugin_stop</span><span class="hl-0">()</span><span class="hl-1">:</span><span class="hl-0"> </span><span class="hl-5">i32</span><span class="hl-0"> {</span><br/><span class="hl-0"> </span><span class="hl-1">return</span><span class="hl-0"> plugin.</span><span class="hl-7">stop</span><span class="hl-0">()</span><br/><span class="hl-0">}</span> </code><button type="button">Copy</button></pre> <p><strong>Note on Plugin IDs:</strong> The plugin ID is automatically derived from your <code>package.json</code> name. For example:</p> <ul> <li><code>@signalk/example-weather-plugin</code> → <code>_signalk_example-weather-plugin</code></li> <li><code>my-simple-plugin</code> → <code>my-simple-plugin</code></li> </ul> <p>This ensures unique plugin IDs (npm guarantees package name uniqueness) and eliminates discrepancies between package name and plugin ID.</p> <h2 id="step-3-configure-build" class="tsd-anchor-link">Step 3: Configure Build<a href="#step-3-configure-build" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../../../assets/icons.svg#icon-anchor"></use></svg></a></h2> <p>Create <code>asconfig.json</code>:</p> <pre><code class="json"><span class="hl-0">{</span><br/><span class="hl-0"> </span><span class="hl-3">&quot;targets&quot;</span><span class="hl-0">: {</span><br/><span class="hl-0"> </span><span class="hl-3">&quot;release&quot;</span><span class="hl-0">: {</span><br/><span class="hl-0"> </span><span class="hl-3">&quot;outFile&quot;</span><span class="hl-0">: </span><span class="hl-4">&quot;plugin.wasm&quot;</span><span class="hl-0">,</span><br/><span class="hl-0"> </span><span class="hl-3">&quot;optimize&quot;</span><span class="hl-0">: </span><span class="hl-2">true</span><span class="hl-0">,</span><br/><span class="hl-0"> </span><span class="hl-3">&quot;shrinkLevel&quot;</span><span class="hl-0">: </span><span class="hl-2">2</span><span class="hl-0">,</span><br/><span class="hl-0"> </span><span class="hl-3">&quot;converge&quot;</span><span class="hl-0">: </span><span class="hl-2">true</span><span class="hl-0">,</span><br/><span class="hl-0"> </span><span class="hl-3">&quot;noAssert&quot;</span><span class="hl-0">: </span><span class="hl-2">true</span><span class="hl-0">,</span><br/><span class="hl-0"> </span><span class="hl-3">&quot;runtime&quot;</span><span class="hl-0">: </span><span class="hl-4">&quot;incremental&quot;</span><span class="hl-0">,</span><br/><span class="hl-0"> </span><span class="hl-3">&quot;exportRuntime&quot;</span><span class="hl-0">: </span><span class="hl-2">true</span><br/><span class="hl-0"> },</span><br/><span class="hl-0"> </span><span class="hl-3">&quot;debug&quot;</span><span class="hl-0">: {</span><br/><span class="hl-0"> </span><span class="hl-3">&quot;outFile&quot;</span><span class="hl-0">: </span><span class="hl-4">&quot;build/plugin.debug.wasm&quot;</span><span class="hl-0">,</span><br/><span class="hl-0"> </span><span class="hl-3">&quot;sourceMap&quot;</span><span class="hl-0">: </span><span class="hl-2">true</span><span class="hl-0">,</span><br/><span class="hl-0"> </span><span class="hl-3">&quot;debug&quot;</span><span class="hl-0">: </span><span class="hl-2">true</span><span class="hl-0">,</span><br/><span class="hl-0"> </span><span class="hl-3">&quot;runtime&quot;</span><span class="hl-0">: </span><span class="hl-4">&quot;incremental&quot;</span><span class="hl-0">,</span><br/><span class="hl-0"> </span><span class="hl-3">&quot;exportRuntime&quot;</span><span class="hl-0">: </span><span class="hl-2">true</span><br/><span class="hl-0"> }</span><br/><span class="hl-0"> },</span><br/><span class="hl-0"> </span><span class="hl-3">&quot;options&quot;</span><span class="hl-0">: {</span><br/><span class="hl-0"> </span><span class="hl-3">&quot;bindings&quot;</span><span class="hl-0">: </span><span class="hl-4">&quot;esm&quot;</span><br/><span class="hl-0"> }</span><br/><span class="hl-0">}</span> </code><button type="button">Copy</button></pre> <p><strong>Important</strong>: <code>exportRuntime: true</code> is <strong>required</strong> for the AssemblyScript loader to work. This exports runtime helper functions like <code>__newString</code> and <code>__getString</code> that the server uses for automatic string conversions.</p> <h2 id="step-4-build" class="tsd-anchor-link">Step 4: Build<a href="#step-4-build" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../../../assets/icons.svg#icon-anchor"></use></svg></a></h2> <pre><code class="bash"><span class="hl-5">npx</span><span class="hl-0"> </span><span class="hl-4">asc</span><span class="hl-0"> </span><span class="hl-4">assembly/index.ts</span><span class="hl-0"> </span><span class="hl-2">--target</span><span class="hl-0"> </span><span class="hl-4">release</span> </code><button type="button">Copy</button></pre> <h2 id="step-5-create-packagejson" class="tsd-anchor-link">Step 5: Create package.json<a href="#step-5-create-packagejson" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../../../assets/icons.svg#icon-anchor"></use></svg></a></h2> <pre><code class="json"><span class="hl-0">{</span><br/><span class="hl-0"> </span><span class="hl-3">&quot;name&quot;</span><span class="hl-0">: </span><span class="hl-4">&quot;my-wasm-plugin&quot;</span><span class="hl-0">,</span><br/><span class="hl-0"> </span><span class="hl-3">&quot;version&quot;</span><span class="hl-0">: </span><span class="hl-4">&quot;0.1.0&quot;</span><span class="hl-0">,</span><br/><span class="hl-0"> </span><span class="hl-3">&quot;keywords&quot;</span><span class="hl-0">: [</span><span class="hl-4">&quot;signalk-wasm-plugin&quot;</span><span class="hl-0">],</span><br/><span class="hl-0"> </span><span class="hl-3">&quot;wasmManifest&quot;</span><span class="hl-0">: </span><span class="hl-4">&quot;plugin.wasm&quot;</span><span class="hl-0">,</span><br/><span class="hl-0"> </span><span class="hl-3">&quot;wasmCapabilities&quot;</span><span class="hl-0">: {</span><br/><span class="hl-0"> </span><span class="hl-3">&quot;dataRead&quot;</span><span class="hl-0">: </span><span class="hl-2">true</span><span class="hl-0">,</span><br/><span class="hl-0"> </span><span class="hl-3">&quot;dataWrite&quot;</span><span class="hl-0">: </span><span class="hl-2">true</span><span class="hl-0">,</span><br/><span class="hl-0"> </span><span class="hl-3">&quot;storage&quot;</span><span class="hl-0">: </span><span class="hl-4">&quot;vfs-only&quot;</span><br/><span class="hl-0"> }</span><br/><span class="hl-0">}</span> </code><button type="button">Copy</button></pre> <blockquote> <p><strong>Important: What makes a WASM plugin?</strong></p> <p>The <strong><code>wasmManifest</code></strong> field is the key identifier that tells Signal K this is a WASM plugin (not a Node.js plugin). It must point to your compiled <code>.wasm</code> file.</p> <p>The package <strong>name can be anything</strong> - scoped (<code>@myorg/my-plugin</code>) or unscoped (<code>my-wasm-plugin</code>). Choose a name that makes sense for your plugin and avoids conflicts on npm.</p> </blockquote> <h2 id="step-6-test-install" class="tsd-anchor-link">Step 6: Test Install<a href="#step-6-test-install" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../../../assets/icons.svg#icon-anchor"></use></svg></a></h2> <p><strong>Option 1: Symlink (Recommended for Development)</strong></p> <p>Symlinking your plugin directory allows you to make changes and rebuild without copying files:</p> <pre><code class="bash"><span class="hl-6"># From your Signal K node_modules directory</span><br/><span class="hl-2">cd</span><span class="hl-0"> </span><span class="hl-4">~/.signalk/node_modules</span><br/><span class="hl-5">ln</span><span class="hl-0"> </span><span class="hl-2">-s</span><span class="hl-0"> </span><span class="hl-4">/path/to/your/my-wasm-plugin</span><span class="hl-0"> </span><span class="hl-4">my-wasm-plugin</span><br/><br/><span class="hl-6"># Now any changes you make and rebuild will be picked up on server restart</span> </code><button type="button">Copy</button></pre> <p><strong>Option 2: Direct Copy</strong></p> <pre><code class="bash"><span class="hl-5">mkdir</span><span class="hl-0"> </span><span class="hl-2">-p</span><span class="hl-0"> </span><span class="hl-4">~/.signalk/node_modules/my-wasm-plugin</span><br/><span class="hl-5">cp</span><span class="hl-0"> </span><span class="hl-4">plugin.wasm</span><span class="hl-0"> </span><span class="hl-4">package.json</span><span class="hl-0"> </span><span class="hl-4">~/.signalk/node_modules/my-wasm-plugin/</span><br/><br/><span class="hl-6"># If your plugin has a public/ folder with web UI:</span><br/><span class="hl-5">cp</span><span class="hl-0"> </span><span class="hl-2">-r</span><span class="hl-0"> </span><span class="hl-4">public</span><span class="hl-0"> </span><span class="hl-4">~/.signalk/node_modules/my-wasm-plugin/</span> </code><button type="button">Copy</button></pre> <p><strong>Option 3: NPM Package Install</strong></p> <pre><code class="bash"><span class="hl-6"># If you&#39;ve packaged with `npm pack`</span><br/><span class="hl-5">npm</span><span class="hl-0"> </span><span class="hl-4">install</span><span class="hl-0"> </span><span class="hl-2">-g</span><span class="hl-0"> </span><span class="hl-4">./my-wasm-plugin-1.0.0.tgz</span><br/><br/><span class="hl-6"># Or install from npm registry (if published)</span><br/><span class="hl-5">npm</span><span class="hl-0"> </span><span class="hl-4">install</span><span class="hl-0"> </span><span class="hl-2">-g</span><span class="hl-0"> </span><span class="hl-4">my-wasm-plugin</span> </code><button type="button">Copy</button></pre> <p><strong>Note</strong>: Symlinking is the most efficient method for development - changes are picked up on server restart without copying files. Use npm install for production deployments or when distributing plugins.</p> <p><strong>Important</strong>: If your plugin includes static files (like a web UI in the <code>public/</code> folder), make sure to copy that folder as well. Static files are automatically served at <code>/plugins/your-plugin-id/</code> when the plugin is loaded.</p> <h2 id="step-7-verify-plugin-configuration-in-admin-ui" class="tsd-anchor-link">Step 7: Verify Plugin Configuration in Admin UI<a href="#step-7-verify-plugin-configuration-in-admin-ui" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../../../assets/icons.svg#icon-anchor"></use></svg></a></h2> <p>After installing your plugin, verify it appears in the Admin UI:</p> <ol> <li> <p><strong>Navigate to Plugin Configuration</strong>: Open the Admin UI at <code>http://your-server:3000/admin/</code> and go to <strong>Server → Plugin Config</strong></p> </li> <li> <p><strong>Check Plugin List</strong>: Your WASM plugin should appear in the list with:</p> <ul> <li>Plugin name (from <code>name()</code> export)</li> <li>Version (from <code>package.json</code>)</li> <li>Enable/Disable toggle</li> <li>Configuration form (based on <code>schema()</code> export)</li> </ul> </li> <li> <p><strong>Verify Configuration Persistence</strong>:</p> <ul> <li>Configuration is saved to <code>~/.signalk/plugin-config-data/your-plugin-id.json</code></li> <li>Changes are applied immediately (plugin restarts automatically)</li> <li>The file structure is:<pre><code class="json"><span class="hl-0">{</span><br/><span class="hl-0"> </span><span class="hl-3">&quot;enabled&quot;</span><span class="hl-0">: </span><span class="hl-2">true</span><span class="hl-0">,</span><br/><span class="hl-0"> </span><span class="hl-3">&quot;enableDebug&quot;</span><span class="hl-0">: </span><span class="hl-2">false</span><span class="hl-0">,</span><br/><span class="hl-0"> </span><span class="hl-3">&quot;configuration&quot;</span><span class="hl-0">: {</span><br/><span class="hl-0"> </span><span class="hl-3">&quot;updateRate&quot;</span><span class="hl-0">: </span><span class="hl-2">1000</span><br/><span class="hl-0"> }</span><br/><span class="hl-0">}</span> </code><button type="button">Copy</button></pre> </li> </ul> </li> <li> <p><strong>Troubleshooting</strong>:</p> <ul> <li>If plugin doesn't appear: Check <code>package.json</code> has the <code>signalk-wasm-plugin</code> keyword and <code>wasmManifest</code> field</li> <li>If configuration form is empty: Verify <code>schema()</code> export returns valid JSON Schema</li> <li>If settings don't persist: Check file permissions on <code>~/.signalk/plugin-config-data/</code></li> </ul> </li> </ol> <p><strong>Important</strong>: The Admin UI shows all plugins (both Node.js and WASM) in a unified list. WASM plugins integrate seamlessly with the existing plugin configuration system.</p> <h2 id="api-reference" class="tsd-anchor-link">API Reference<a href="#api-reference" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../../../assets/icons.svg#icon-anchor"></use></svg></a></h2> <h3 id="base-classes" class="tsd-anchor-link">Base Classes<a href="#base-classes" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../../../assets/icons.svg#icon-anchor"></use></svg></a></h3> <h4 id="_" class="tsd-anchor-link"><code>Plugin</code><a href="#_" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../../../assets/icons.svg#icon-anchor"></use></svg></a></h4> <p>Abstract base class for all plugins.</p> <p><strong>Methods to implement:</strong></p> <ul> <li><code>id(): string</code> - Unique plugin identifier</li> <li><code>name(): string</code> - Human-readable name</li> <li><code>schema(): string</code> - JSON schema for configuration</li> <li><code>start(config: string): i32</code> - Initialize plugin</li> <li><code>stop(): i32</code> - Clean shutdown</li> </ul> <h3 id="signal-k-types" class="tsd-anchor-link">Signal K Types<a href="#signal-k-types" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../../../assets/icons.svg#icon-anchor"></use></svg></a></h3> <h4 id="_-1" class="tsd-anchor-link"><code>Delta</code><a href="#_-1" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../../../assets/icons.svg#icon-anchor"></use></svg></a></h4> <p>Represents a Signal K delta message.</p> <pre><code class="typescript"><span class="hl-1">const</span><span class="hl-0"> </span><span class="hl-2">delta</span><span class="hl-0"> </span><span class="hl-1">=</span><span class="hl-0"> </span><span class="hl-1">new</span><span class="hl-0"> </span><span class="hl-7">Delta</span><span class="hl-0">(</span><span class="hl-4">&#39;vessels.self&#39;</span><span class="hl-0">, [update])</span> </code><button type="button">Copy</button></pre> <h4 id="_-2" class="tsd-anchor-link"><code>Update</code><a href="#_-2" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../../../assets/icons.svg#icon-anchor"></use></svg></a></h4> <p>Represents an update within a delta. The server automatically adds <code>$source</code> and <code>timestamp</code>.</p> <pre><code class="typescript"><span class="hl-1">const</span><span class="hl-0"> </span><span class="hl-2">update</span><span class="hl-0"> </span><span class="hl-1">=</span><span class="hl-0"> </span><span class="hl-1">new</span><span class="hl-0"> </span><span class="hl-7">Update</span><span class="hl-0">([pathValue])</span> </code><button type="button">Copy</button></pre> <h4 id="_-3" class="tsd-anchor-link"><code>PathValue</code><a href="#_-3" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../../../assets/icons.svg#icon-anchor"></use></svg></a></h4> <p>Represents a path-value pair.</p> <pre><code class="typescript"><span class="hl-1">const</span><span class="hl-0"> </span><span class="hl-2">pathValue</span><span class="hl-0"> </span><span class="hl-1">=</span><span class="hl-0"> </span><span class="hl-1">new</span><span class="hl-0"> </span><span class="hl-7">PathValue</span><span class="hl-0">(</span><span class="hl-4">&#39;navigation.position&#39;</span><span class="hl-0">, positionJson)</span> </code><button type="button">Copy</button></pre> <h4 id="_-4" class="tsd-anchor-link"><code>Position</code><a href="#_-4" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../../../assets/icons.svg#icon-anchor"></use></svg></a></h4> <p>GPS position with latitude/longitude.</p> <pre><code class="typescript"><span class="hl-1">const</span><span class="hl-0"> </span><span class="hl-2">pos</span><span class="hl-0"> </span><span class="hl-1">=</span><span class="hl-0"> </span><span class="hl-1">new</span><span class="hl-0"> </span><span class="hl-7">Position</span><span class="hl-0">(</span><span class="hl-2">60.1</span><span class="hl-0">, </span><span class="hl-2">24.9</span><span class="hl-0">)</span><br/><span class="hl-1">const</span><span class="hl-0"> </span><span class="hl-2">posJson</span><span class="hl-0"> </span><span class="hl-1">=</span><span class="hl-0"> pos.</span><span class="hl-7">toJSON</span><span class="hl-0">()</span> </code><button type="button">Copy</button></pre> <h4 id="_-5" class="tsd-anchor-link"><code>Notification</code><a href="#_-5" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../../../assets/icons.svg#icon-anchor"></use></svg></a></h4> <p>Signal K notification.</p> <pre><code class="typescript"><span class="hl-1">const</span><span class="hl-0"> </span><span class="hl-2">notif</span><span class="hl-0"> </span><span class="hl-1">=</span><span class="hl-0"> </span><span class="hl-1">new</span><span class="hl-0"> </span><span class="hl-7">Notification</span><span class="hl-0">(NotificationState.normal, </span><span class="hl-4">&#39;Hello!&#39;</span><span class="hl-0">)</span><br/><span class="hl-1">const</span><span class="hl-0"> </span><span class="hl-2">notifJson</span><span class="hl-0"> </span><span class="hl-1">=</span><span class="hl-0"> notif.</span><span class="hl-7">toJSON</span><span class="hl-0">()</span> </code><button type="button">Copy</button></pre> <h3 id="api-functions" class="tsd-anchor-link">API Functions<a href="#api-functions" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../../../assets/icons.svg#icon-anchor"></use></svg></a></h3> <h4 id="_-6" class="tsd-anchor-link"><code>emit(delta: Delta): void</code><a href="#_-6" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../../../assets/icons.svg#icon-anchor"></use></svg></a></h4> <p>Emit a delta message to Signal K server.</p> <pre><code class="typescript"><span class="hl-7">emit</span><span class="hl-0">(delta)</span> </code><button type="button">Copy</button></pre> <p><strong>Requires capability:</strong> <code>dataWrite: true</code></p> <h4 id="_-7" class="tsd-anchor-link"><code>setStatus(message: string): void</code><a href="#_-7" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../../../assets/icons.svg#icon-anchor"></use></svg></a></h4> <p>Set plugin status (shown in admin UI).</p> <pre><code class="typescript"><span class="hl-7">setStatus</span><span class="hl-0">(</span><span class="hl-4">&#39;Running normally&#39;</span><span class="hl-0">)</span> </code><button type="button">Copy</button></pre> <h4 id="_-8" class="tsd-anchor-link"><code>setError(message: string): void</code><a href="#_-8" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../../../assets/icons.svg#icon-anchor"></use></svg></a></h4> <p>Report an error (shown in admin UI).</p> <pre><code class="typescript"><span class="hl-7">setError</span><span class="hl-0">(</span><span class="hl-4">&#39;Sensor connection failed&#39;</span><span class="hl-0">)</span> </code><button type="button">Copy</button></pre> <h4 id="_-9" class="tsd-anchor-link"><code>debug(message: string): void</code><a href="#_-9" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../../../assets/icons.svg#icon-anchor"></use></svg></a></h4> <p>Log debug message to server logs.</p> <pre><code class="typescript"><span class="hl-7">debug</span><span class="hl-0">(</span><span class="hl-4">&#39;Processing data: &#39;</span><span class="hl-0"> </span><span class="hl-1">+</span><span class="hl-0"> value.</span><span class="hl-7">toString</span><span class="hl-0">())</span> </code><button type="button">Copy</button></pre> <h4 id="_-10" class="tsd-anchor-link"><code>getSelfPath(path: string): string | null</code><a href="#_-10" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../../../assets/icons.svg#icon-anchor"></use></svg></a></h4> <p>Read data from vessel.self.</p> <pre><code class="typescript"><span class="hl-1">const</span><span class="hl-0"> </span><span class="hl-2">speedJson</span><span class="hl-0"> </span><span class="hl-1">=</span><span class="hl-0"> </span><span class="hl-7">getSelfPath</span><span class="hl-0">(</span><span class="hl-4">&#39;navigation.speedOverGround&#39;</span><span class="hl-0">)</span><br/><span class="hl-1">if</span><span class="hl-0"> (speedJson </span><span class="hl-1">!==</span><span class="hl-0"> </span><span class="hl-2">null</span><span class="hl-0">) {</span><br/><span class="hl-0"> </span><span class="hl-1">const</span><span class="hl-0"> </span><span class="hl-2">speed</span><span class="hl-0"> </span><span class="hl-1">=</span><span class="hl-0"> </span><span class="hl-7">parseFloat</span><span class="hl-0">(speedJson)</span><br/><span class="hl-0">}</span> </code><button type="button">Copy</button></pre> <p><strong>Requires capability:</strong> <code>dataRead: true</code></p> <h4 id="_-11" class="tsd-anchor-link"><code>getPath(path: string): string | null</code><a href="#_-11" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../../../assets/icons.svg#icon-anchor"></use></svg></a></h4> <p>Read data from any context.</p> <pre><code class="typescript"><span class="hl-1">const</span><span class="hl-0"> </span><span class="hl-2">posJson</span><span class="hl-0"> </span><span class="hl-1">=</span><span class="hl-0"> </span><span class="hl-7">getPath</span><span class="hl-0">(</span><span class="hl-4">&#39;vessels.self.navigation.position&#39;</span><span class="hl-0">)</span> </code><button type="button">Copy</button></pre> <p><strong>Requires capability:</strong> <code>dataRead: true</code></p> <h4 id="_-12" class="tsd-anchor-link"><code>readConfig(): string</code><a href="#_-12" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../../../assets/icons.svg#icon-anchor"></use></svg></a></h4> <p>Read plugin configuration.</p> <pre><code class="typescript"><span class="hl-1">const</span><span class="hl-0"> </span><span class="hl-2">configJson</span><span class="hl-0"> </span><span class="hl-1">=</span><span class="hl-0"> </span><span class="hl-7">readConfig</span><span class="hl-0">()</span> </code><button type="button">Copy</button></pre> <h4 id="_-13" class="tsd-anchor-link"><code>saveConfig(configJson: string): i32</code><a href="#_-13" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../../../assets/icons.svg#icon-anchor"></use></svg></a></h4> <p>Save plugin configuration.</p> <pre><code class="typescript"><span class="hl-1">const</span><span class="hl-0"> </span><span class="hl-2">result</span><span class="hl-0"> </span><span class="hl-1">=</span><span class="hl-0"> </span><span class="hl-7">saveConfig</span><span class="hl-0">(</span><span class="hl-2">JSON</span><span class="hl-0">.</span><span class="hl-7">stringify</span><span class="hl-0">(config))</span><br/><span class="hl-1">if</span><span class="hl-0"> (result </span><span class="hl-1">!==</span><span class="hl-0"> </span><span class="hl-2">0</span><span class="hl-0">) {</span><br/><span class="hl-0"> </span><span class="hl-7">setError</span><span class="hl-0">(</span><span class="hl-4">&#39;Failed to save config&#39;</span><span class="hl-0">)</span><br/><span class="hl-0">}</span> </code><button type="button">Copy</button></pre> <h3 id="helper-functions" class="tsd-anchor-link">Helper Functions<a href="#helper-functions" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../../../assets/icons.svg#icon-anchor"></use></svg></a></h3> <pre><code class="typescript"><span class="hl-1">import</span><span class="hl-0"> {</span><br/><span class="hl-0"> createSimpleDelta,</span><br/><span class="hl-0"> getCurrentTimestamp</span><br/><span class="hl-0">} </span><span class="hl-1">from</span><span class="hl-0"> </span><span class="hl-4">&#39;@signalk/assemblyscript-plugin-sdk&#39;</span><br/><br/><span class="hl-6">// Quick delta creation</span><br/><span class="hl-1">const</span><span class="hl-0"> </span><span class="hl-2">delta</span><span class="hl-0"> </span><span class="hl-1">=</span><span class="hl-0"> </span><span class="hl-7">createSimpleDelta</span><span class="hl-0">(</span><span class="hl-4">&#39;my-plugin&#39;</span><span class="hl-0">, </span><span class="hl-4">&#39;test.value&#39;</span><span class="hl-0">, </span><span class="hl-4">&#39;&quot;hello&quot;&#39;</span><span class="hl-0">)</span><br/><span class="hl-7">emit</span><span class="hl-0">(delta)</span> </code><button type="button">Copy</button></pre> <h3 id="json-parsing" class="tsd-anchor-link">JSON Parsing<a href="#json-parsing" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../../../assets/icons.svg#icon-anchor"></use></svg></a></h3> <p>The SDK includes <a href="https://github.com/near/assemblyscript-json">assemblyscript-json</a> for parsing JSON data. This is useful when working with configuration, API responses, or resource provider requests.</p> <pre><code class="typescript"><span class="hl-1">import</span><span class="hl-0"> { JSON } </span><span class="hl-1">from</span><span class="hl-0"> </span><span class="hl-4">&#39;@signalk/assemblyscript-plugin-sdk/assembly&#39;</span><br/><br/><span class="hl-6">// Parse a JSON string</span><br/><span class="hl-1">const</span><span class="hl-0"> </span><span class="hl-2">jsonStr</span><span class="hl-0"> </span><span class="hl-1">=</span><span class="hl-0"> </span><span class="hl-4">&#39;{&quot;name&quot;: &quot;My Boat&quot;, &quot;speed&quot;: 5.2}&#39;</span><br/><span class="hl-1">const</span><span class="hl-0"> </span><span class="hl-2">parsed</span><span class="hl-0"> </span><span class="hl-1">=</span><span class="hl-0"> </span><span class="hl-2">JSON</span><span class="hl-0">.</span><span class="hl-7">parse</span><span class="hl-0">(jsonStr)</span><br/><br/><span class="hl-1">if</span><span class="hl-0"> (parsed.isObj) {</span><br/><span class="hl-0"> </span><span class="hl-1">const</span><span class="hl-0"> </span><span class="hl-2">obj</span><span class="hl-0"> </span><span class="hl-1">=</span><span class="hl-0"> parsed </span><span class="hl-1">as</span><span class="hl-0"> </span><span class="hl-5">JSON</span><span class="hl-0">.</span><span class="hl-5">Obj</span><br/><br/><span class="hl-0"> </span><span class="hl-6">// Get string values</span><br/><span class="hl-0"> </span><span class="hl-1">const</span><span class="hl-0"> </span><span class="hl-2">nameValue</span><span class="hl-0"> </span><span class="hl-1">=</span><span class="hl-0"> obj.</span><span class="hl-7">getString</span><span class="hl-0">(</span><span class="hl-4">&#39;name&#39;</span><span class="hl-0">)</span><br/><span class="hl-0"> </span><span class="hl-1">if</span><span class="hl-0"> (nameValue </span><span class="hl-1">!==</span><span class="hl-0"> </span><span class="hl-2">null</span><span class="hl-0">) {</span><br/><span class="hl-0"> </span><span class="hl-1">const</span><span class="hl-0"> </span><span class="hl-2">name</span><span class="hl-0"> </span><span class="hl-1">=</span><span class="hl-0"> nameValue.</span><span class="hl-7">valueOf</span><span class="hl-0">() </span><span class="hl-6">// &quot;My Boat&quot;</span><br/><span class="hl-0"> }</span><br/><br/><span class="hl-0"> </span><span class="hl-6">// Get number values</span><br/><span class="hl-0"> </span><span class="hl-1">const</span><span class="hl-0"> </span><span class="hl-2">speedValue</span><span class="hl-0"> </span><span class="hl-1">=</span><span class="hl-0"> obj.</span><span class="hl-7">getNum</span><span class="hl-0">(</span><span class="hl-4">&#39;speed&#39;</span><span class="hl-0">)</span><br/><span class="hl-0"> </span><span class="hl-1">if</span><span class="hl-0"> (speedValue </span><span class="hl-1">!==</span><span class="hl-0"> </span><span class="hl-2">null</span><span class="hl-0">) {</span><br/><span class="hl-0"> </span><span class="hl-1">const</span><span class="hl-0"> </span><span class="hl-2">speed</span><span class="hl-0"> </span><span class="hl-1">=</span><span class="hl-0"> speedValue.</span><span class="hl-7">valueOf</span><span class="hl-0">() </span><span class="hl-6">// 5.2 (as f64)</span><br/><span class="hl-0"> }</span><br/><span class="hl-0">}</span> </code><button type="button">Copy</button></pre> <p><strong>Available methods on <code>JSON.Obj</code>:</strong></p> <ul> <li><code>getString(key)</code> - Returns <code>JSON.Str | null</code></li> <li><code>getNum(key)</code> - Returns <code>JSON.Num | null</code></li> <li><code>getBool(key)</code> - Returns <code>JSON.Bool | null</code></li> <li><code>getObj(key)</code> - Returns <code>JSON.Obj | null</code></li> <li><code>getArr(key)</code> - Returns <code>JSON.Arr | null</code></li> <li><code>getValue(key)</code> - Returns <code>JSON.Value | null</code></li> </ul> <p><strong>Note:</strong> Plugins using resource providers or parsing complex JSON should add <code>assemblyscript-json</code> to their dependencies:</p> <pre><code class="bash"><span class="hl-5">npm</span><span class="hl-0"> </span><span class="hl-4">install</span><span class="hl-0"> </span><span class="hl-4">assemblyscript-json</span> </code><button type="button">Copy</button></pre> <h3 id="json-value-encoding" class="tsd-anchor-link">JSON Value Encoding<a href="#json-value-encoding" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../../../assets/icons.svg#icon-anchor"></use></svg></a></h3> <p>Values must be JSON-encoded strings:</p> <pre><code class="typescript"><span class="hl-6">// Numbers</span><br/><span class="hl-1">const</span><span class="hl-0"> </span><span class="hl-2">pathValue</span><span class="hl-0"> </span><span class="hl-1">=</span><span class="hl-0"> </span><span class="hl-1">new</span><span class="hl-0"> </span><span class="hl-7">PathValue</span><span class="hl-0">(</span><span class="hl-4">&#39;temperature&#39;</span><span class="hl-0">, </span><span class="hl-4">&#39;25.5&#39;</span><span class="hl-0">)</span><br/><br/><span class="hl-6">// Strings (note the quotes)</span><br/><span class="hl-1">const</span><span class="hl-0"> </span><span class="hl-2">pathValue</span><span class="hl-0"> </span><span class="hl-1">=</span><span class="hl-0"> </span><span class="hl-1">new</span><span class="hl-0"> </span><span class="hl-7">PathValue</span><span class="hl-0">(</span><span class="hl-4">&#39;name&#39;</span><span class="hl-0">, </span><span class="hl-4">&#39;&quot;My Boat&quot;&#39;</span><span class="hl-0">)</span><br/><br/><span class="hl-6">// Objects</span><br/><span class="hl-1">const</span><span class="hl-0"> </span><span class="hl-2">pathValue</span><span class="hl-0"> </span><span class="hl-1">=</span><span class="hl-0"> </span><span class="hl-1">new</span><span class="hl-0"> </span><span class="hl-7">PathValue</span><span class="hl-0">(</span><br/><span class="hl-0"> </span><span class="hl-4">&#39;position&#39;</span><span class="hl-0">,</span><br/><span class="hl-0"> </span><span class="hl-4">&#39;{&quot;latitude&quot;:60.1,&quot;longitude&quot;:24.9}&#39;</span><br/><span class="hl-0">)</span><br/><br/><span class="hl-6">// Use helper classes</span><br/><span class="hl-1">const</span><span class="hl-0"> </span><span class="hl-2">pos</span><span class="hl-0"> </span><span class="hl-1">=</span><span class="hl-0"> </span><span class="hl-1">new</span><span class="hl-0"> </span><span class="hl-7">Position</span><span class="hl-0">(</span><span class="hl-2">60.1</span><span class="hl-0">, </span><span class="hl-2">24.9</span><span class="hl-0">)</span><br/><span class="hl-1">const</span><span class="hl-0"> </span><span class="hl-2">pathValue</span><span class="hl-0"> </span><span class="hl-1">=</span><span class="hl-0"> </span><span class="hl-1">new</span><span class="hl-0"> </span><span class="hl-7">PathValue</span><span class="hl-0">(</span><span class="hl-4">&#39;position&#39;</span><span class="hl-0">, pos.</span><span class="hl-7">toJSON</span><span class="hl-0">())</span> </code><button type="button">Copy</button></pre> <h2 id="resource-providers" class="tsd-anchor-link">Resource Providers<a href="#resource-providers" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../../../assets/icons.svg#icon-anchor"></use></svg></a></h2> <p>WASM plugins can register as <strong>resource provi