> ## Documentation Index
> Fetch the complete documentation index at: https://noorle.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# JavaScript

> Build Noorle plugins with JavaScript for quick prototyping and flexibility

## Overview

JavaScript offers the fastest path to building Noorle plugins. Using ComponentizeJS, you can compile standard JavaScript directly to WebAssembly components without a separate build toolchain.

<Note>
  JavaScript plugins share the same ComponentizeJS toolchain as TypeScript. If you prefer type safety, see the [TypeScript guide](/build/languages/typescript).
</Note>

## Prerequisites

* Node.js 18+ installed
* Noorle CLI installed and authenticated
* Basic familiarity with the [plugin project structure](/build/plugins/project-structure)

## Quick Start

<Steps>
  ### Install ComponentizeJS

  ```bash theme={null}
  npm install -g @bytecodealliance/componentize-js @bytecodealliance/jco
  ```

  ### Create your project

  ```bash theme={null}
  mkdir my-plugin && cd my-plugin
  npm init -y
  ```

  ### Define the WIT interface

  Create `world.wit`:

  ```wit theme={null}
  package noorle:plugin;

  world plugin {
    export tool: interface {
      call: func(name: string, input: string) -> string;
      list: func() -> string;
    }
  }
  ```

  ### Write your plugin

  Create `plugin.js`:

  ```javascript theme={null}
  export const tool = {
    list() {
      return JSON.stringify([
        {
          name: "hello",
          description: "Returns a greeting",
          inputSchema: {
            type: "object",
            properties: {
              name: { type: "string", description: "Name to greet" }
            },
            required: ["name"]
          }
        }
      ]);
    },

    call(name, input) {
      const args = JSON.parse(input);

      switch (name) {
        case "hello":
          return JSON.stringify({
            content: [{ type: "text", text: `Hello, ${args.name}!` }]
          });
        default:
          return JSON.stringify({
            error: `Unknown tool: ${name}`
          });
      }
    }
  };
  ```

  ### Build the WASM component

  ```bash theme={null}
  jco componentize plugin.js --wit world.wit -o plugin.wasm
  ```

  ### Add configuration

  Create `noorle.yaml`:

  ```yaml theme={null}
  schema_version: "1.0"
  metadata:
    name: my-js-plugin
    description: A simple greeting plugin
    version: 0.1.0
  ```

  ### Package and upload

  ```bash theme={null}
  tar czf my-plugin.npack plugin.wasm noorle.yaml
  noorle plugin push my-plugin.npack
  ```
</Steps>

## Working with External Data

JavaScript plugins can process and transform data:

```javascript theme={null}
export const tool = {
  list() {
    return JSON.stringify([
      {
        name: "parse_csv",
        description: "Parse CSV text into structured JSON",
        inputSchema: {
          type: "object",
          properties: {
            csv: { type: "string", description: "CSV content" },
            hasHeaders: { type: "boolean", description: "Whether first row is headers" }
          },
          required: ["csv"]
        }
      }
    ]);
  },

  call(name, input) {
    const args = JSON.parse(input);

    if (name === "parse_csv") {
      const lines = args.csv.trim().split("\n");
      const hasHeaders = args.hasHeaders !== false;
      const headers = hasHeaders
        ? lines[0].split(",").map(h => h.trim())
        : lines[0].split(",").map((_, i) => `col_${i}`);
      const dataLines = hasHeaders ? lines.slice(1) : lines;

      const rows = dataLines.map(line => {
        const values = line.split(",").map(v => v.trim());
        const row = {};
        headers.forEach((h, i) => { row[h] = values[i] || ""; });
        return row;
      });

      return JSON.stringify({
        content: [{ type: "text", text: JSON.stringify(rows, null, 2) }]
      });
    }

    return JSON.stringify({ error: `Unknown tool: ${name}` });
  }
};
```

## Error Handling

Return structured errors so agents can understand what went wrong:

```javascript theme={null}
call(name, input) {
  try {
    const args = JSON.parse(input);
    // ... tool logic
  } catch (err) {
    return JSON.stringify({
      isError: true,
      content: [{
        type: "text",
        text: `Error: ${err.message}`
      }]
    });
  }
}
```

## JavaScript vs TypeScript

| Aspect      | JavaScript                           | TypeScript                         |
| ----------- | ------------------------------------ | ---------------------------------- |
| Setup       | Simpler — no compile step for source | Requires `tsc` before componentize |
| Type safety | None — runtime errors only           | Compile-time type checking         |
| Toolchain   | `jco componentize` directly          | `tsc` → `jco componentize`         |
| Best for    | Quick prototyping, simple tools      | Production plugins, complex logic  |

Both use the same ComponentizeJS runtime and produce identical WASM output. The choice is purely about development experience.

## Limitations

<Warning>
  JavaScript plugins run in a WebAssembly sandbox. The following are **not available**:

  * `fetch()` or network APIs (use [permissions](/build/plugins/permissions-and-security) for network access)
  * `fs` module (use declared filesystem permissions)
  * `setTimeout` / `setInterval`
  * Dynamic `import()`
</Warning>

## Next Steps

<CardGroup cols={2}>
  <Card title="Configuration" icon="gear" href="/build/configuration">
    Full noorle.yaml reference
  </Card>

  <Card title="Permissions" icon="shield" href="/build/plugins/permissions-and-security">
    Configure network and filesystem access
  </Card>

  <Card title="Publishing" icon="rocket" href="/build/deployment/publishing-and-versioning">
    Upload and version your plugin
  </Card>

  <Card title="TypeScript Guide" icon="code" href="/build/languages/typescript">
    Add type safety to your plugin
  </Card>
</CardGroup>
