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

# Engine

> The TypeScript source language and the engine API that rules call.

```ts theme={null}
import { typescript, Engine } from "@usenarrator/lang-ts";
import { oxcParser } from "@usenarrator/lang-ts/oxc";
import { createWasmParser } from "@usenarrator/lang-ts/wasm";
```

## typescript()

```ts theme={null}
function typescript(options: {
  parser: Parser;
  plugins?: (TsPlugin | TsPlugin[])[];
  setup?: (ctx: { engine: Engine; path: string }) => void;
  dependencies?: (path: string) => Record<string, string> | undefined;
}): SourceLanguage & { engine(locale: Locale): Engine };
```

<ParamField path="parser" type="Parser" required>
  `oxcParser` for Node and Bun, or the parser that `await createWasmParser()` resolves to for browsers, workers and edge runtimes. `typescript()` throws a readable error if you pass something else, such as the Promise itself. See [Embedding](/guides/embedding).
</ParamField>

<ParamField path="plugins" type="(TsPlugin | TsPlugin[])[]">
  Library and codebase plugins, applied after the built-in `std` plugin. Nested arrays are flattened. Later plugins win.
</ParamField>

<ParamField path="setup" type="({ engine, path }) => void">
  Runs before each file is narrated. Use it to install cross-file hooks, such as `engine.typeOfCall`, which lets the engine look up the declared return type of a function defined in another file.
</ParamField>

<ParamField path="dependencies" type="(path) => Record<string, string> | undefined">
  A fallback source of package dependencies per file. Normally you pass a dependency index to `createNarrator` instead, which takes precedence over this option. See [Dependency detection](/concepts/dependency-detection).
</ParamField>

The language handles `.ts`, `.tsx`, `.js`, `.jsx`, `.mjs` and `.cjs`, but not `.d.ts`. Its `ecosystems` are `["npm"]`. Its extra `engine(locale)` method creates a bare engine, which is handy in tools and tests.

```ts theme={null}
type Parser = (filename: string, src: string) => ParseOutput;
type ParseOutput = { program: any; comments: { type: string; value: string; start: number; end: number }[]; errors: unknown[] };
```

## createWasmParser()

```ts theme={null}
function createWasmParser(options?: {
  wasm?: URL | string | Response | ArrayBuffer | ArrayBufferView | WebAssembly.Module | PromiseLike<Response | WebAssembly.Module>;
}): Promise<Parser>;
```

Loads oxc's WASM build, which ships inside `@usenarrator/lang-ts`, and resolves to a synchronous `Parser`. Create it once and reuse it: every call starts a new WASM instance.

<ParamField path="wasm" type="URL | string | Response | bytes | WebAssembly.Module">
  Where the `.wasm` file comes from. Leave it out in Node, Bun and bundlers that turn `new URL(…, import.meta.url)` into an asset, such as Vite. Pass a compiled module on Cloudflare Workers, imported from `@usenarrator/lang-ts/wasm.wasm`, and a URL inside a browser extension. If the value is not a WebAssembly file, for example an HTML page served instead of the `.wasm`, the error says so.
</ParamField>

## Syntax errors and failing rules

A file with a syntax error is still narrated. oxc recovers from some errors on its own, such as a `return` outside a function, and the file reads as usual. When an error stops the parser, the engine blanks out the fewest whole lines that let the rest parse (falling back to whole top-level statements), narrates everything else, and puts a note where the gap is, such as "Line 12 has a syntax error, so it's left out." The narration's `errors` still counts every error the parser reported, each one is listed in `problems` with `source: "parser"`, and the note's text comes from the locale's `statements.unreadable` phrase.

A plugin rule that throws or returns something unusable is skipped as if it had returned `null`. Each one is listed in `problems` with `source: "plugin"`, `severity: "warning"`, the `plugin` name and the `rule`, and counted in `stats.ruleErrors`. See [When a rule fails](/guides/writing-a-plugin#when-a-rule-fails).

## The Engine inside rules

Every rule receives the engine as `e`. These are the methods plugins in the repository use, roughly from most to least common.

### Rendering expressions

| Method | Returns | Description |
| - | - | - |
| `e.text(node)` | `string` | Inline text for any expression. Block lines it needs are attached to your rule's result automatically. |
| `e.noun(node)` | `Doc` | Inline text plus block lines, for when you need to place the lines yourself. |
| `e.cond(node, neg?)` | `Doc` | Renders an expression as a yes or no condition, optionally negated. |
| `e.call(node, stmt)` | `Doc` | Renders a call as the engine would, including other plugins' rules. |
| `e.literal(node)` | `string` | Renders a literal. |
| `e.code(node)` | `string` | The node's original source text. |
| `e.raw(node, reason?)` | `string` | The source as a `c` markup token. Counts as a fallback in stats. |
| `e.typeText(typeNode)` | `string` | Renders a type annotation. |
| `e.fold(node)` | `number \| null` | Constant-folds arithmetic like `60 * 60 * 24`. |

### The current file

These describe the file being narrated. They are set before any rule runs.

| Member | Description |
| - | - |
| `e.usesLibrary(lib)` | `true` when the file imports `lib` or a subpath of it, or its package depends on `lib`. The standard guard for library plugins. |
| `e.libraryMajor(lib)` | The major version of `lib` the file's package declares, or `null`. Use it to pick a reading per major. |
| `e.imports` | A `Map` from each imported local name to `{ from, name }`. `import { a as b } from "x"` gives `b → { from: "x", name: "a" }`, and a default import has `name: "default"`. |
| `e.program` | The file's syntax tree. Use it, or the engine itself, as a cache key for facts you compute once per file. |
| `e.path` | The file's path as the host passed it. The CLI and the browser extension pass repository-relative paths. |
| `e.dependencies` | The file's package dependencies, name to version range. Empty when the host has no manifests. |
| `e.src` | The source text of the file. |

### Names

| Method | Description |
| - | - |
| `e.ref(name)` | A variable reference as a value token, with its display words. |
| `e.prop(key)` | A property or key name as a value token. |
| `e.fnRef(name, text)` | A function reference token. |
| `e.lex` | The [Lexicon](/reference/core#lexicon) for this file, with `humanize`, `words` and friends. |
| `e.isAmbient(node)` | Whether a node is a plumbing name such as `ctx`. |
| `e.patternNames(pattern)` | The names bound by a destructuring pattern. |

### Arguments, objects and functions

| Method | Description |
| - | - |
| `e.argList(args)` | Rendered argument list as a `Doc`. |
| `e.objectProp(prop)` | One property of an object literal as a `Doc`. |
| `e.lambdaExpr(fn)` | A function's single expression body, or `null` if it has statements. |
| `e.body(node, d)` | Renders statements into a detached `Line[]` at relative depth `d`. |
| `e.looksBoolean(node)` | Whether an expression is probably a yes or no value. |

### Emitting lines (statement rules)

| Method | Description |
| - | - |
| `e.emitDoc(d, doc, node, end?, kind?)` | Emits a `Doc` as a line at depth `d`, followed by its block lines. `end` defaults to `"."`. |
| `e.emit(d, text, node, kind?)` | Emits a single line. |
| `e.bullet(doc, d?, kind?)` | Turns a `Doc` into bullet lines. |

### State

| Field | Description |
| - | - |
| `e.say` | The locale's core phrases. |
| `e.g` | The locale's grammar. |
| `e.locale` | The active locale. |
| `e.stats` | Node and fallback counts, plus `ruleErrors`: every plugin rule that threw or returned something unusable, as `{ plugin, rule, message, count }`. |
| `e.parse` | The parser, if a rule needs to parse a fragment. |
| `e.phrasesFor(plugin)` | Another plugin's phrasebook for the active locale, merged key by key over its English, for plugins that render each other's phrases. |

<Warning>
  The Engine is a large class and most of its members are public. The methods above are the ones plugins rely on today. Others are internal to the walker and may change without notice.
</Warning>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.