Skip to content

TypeScript WASM Nodes

Flow-Like’s TypeScript SDK uses standard TypeScript/JavaScript, esbuild, and Bytecode Alliance’s componentize-js. The result is a WASM Component that implements Flow-Like’s WIT world.

This is the supported TypeScript path. You do not need AssemblyScript or Javy.

Copy templates/wasm-node-typescript, then run:

Terminal window
mise run setup
mise run test
mise run build

The build task installs Node.js 22 dependencies, copies the canonical WIT file, bundles src/app.ts, and componentizes it to:

build/node.wasm

Without mise:

Terminal window
npm install
npm test
npm run build

The project depends on @flow-like/wasm-sdk-typescript and @bytecodealliance/componentize-js.

Edit src/node.ts. The template’s src/app.ts supplies the WIT bridge and exports:

src/node.ts
import {
type Context,
type ExecutionResult,
NodeDefinition,
PinDefinition,
PinType,
} from "@flow-like/wasm-sdk-typescript";
export function getDefinition(): NodeDefinition {
const node = new NodeDefinition(
"uppercase_ts",
"Uppercase",
"Converts text to uppercase",
"Custom/Text",
);
node.addPin(PinDefinition.inputExec("exec"));
node.addPin(
PinDefinition.inputPin("text", PinType.STRING, {
defaultValue: "",
}),
);
node.addPin(PinDefinition.outputExec("exec_out"));
node.addPin(PinDefinition.outputPin("result", PinType.STRING));
return node;
}
export function run(ctx: Context): ExecutionResult {
const text = ctx.getString("text", "") ?? "";
ctx.setOutput("result", text.toUpperCase());
ctx.activateExec("exec_out");
return ctx.success();
}

Keep the node name and pin names stable after publishing; boards persist those identifiers.

The SDK exports constants for the Flow-Like value types:

ConstantValue
PinType.STRINGString
PinType.I6464-bit integer
PinType.F6464-bit float
PinType.BOOLBoolean
PinType.GENERICJSON value
PinType.BYTESBinary data

Use PinDefinition.inputExec and outputExec for flow-control pins. The SDK also supports struct schemas, collections, defaults, options, and sensitive inputs.

Declare permissions on the node definition:

node.addPermission("network:http");
node.addPermission("streaming");

These labels are exported with the node and configure its execution sandbox. Other common labels include storage:read, storage:write, variables, cache, models, a2ui, oauth, and functions.

Package memory and timeout limits belong in flow-like.toml; see the manifest reference.

The context reads typed inputs and writes outputs:

const name = ctx.getString("name", "") ?? "";
const count = ctx.getI64("count", 1) ?? 1;
ctx.setOutput("result", name.repeat(Math.max(count, 0)));

The template’s bridge also connects logging, streaming, variables, cache, storage, models, OAuth, and HTTP to Flow-Like host imports. Declare the matching permission before calling a gated host service.

The checked-in TypeScript template exposes one getDefinition/run pair. To ship multiple nodes, keep the WIT entry point responsible for returning every definition and dispatching run by ctx.nodeName. Use the repository’s multi-node SDK/package helpers as the reference rather than adding [[nodes]] tables to the manifest; manifest node tables are not part of the current typed manifest.

The template uses Vitest:

Terminal window
mise run test

Tests run the TypeScript node logic with a mock host, so they are fast and do not require the desktop app. Run mise run build as a separate integration check because successful unit tests do not prove that all dependencies can be componentized.

  1. Run mise run build.
  2. Open Flow-Like Desktop.
  3. Go to Library → Packages → Publish.
  4. Select build/node.wasm and flow-like.toml.
  5. Review the nodes extracted from the binary and submit.