Documentation menu

Typed Handlebars API

goldar/typed-handlebars exposes the programmatic language service, persistent compiler and TypeScript backends, and source-map types. goldar/language-server exposes the embeddable server. Normal applications use goldar dev, goldar build, and the goldar/compiler/client TypeScript declarations; these APIs are for editor clients and tooling.

All offsets are zero-based UTF-16 offsets. Language-server line and character positions follow LSP coordinates. Callers must open a document before changing, querying, or closing it.

Programmatic language service

Create one TypedHandlebarsLanguageService per TypeScript project:

import { TypedHandlebarsLanguageService } from "goldar/typed-handlebars";

const service = await TypedHandlebarsLanguageService.create({
	projectRoot: process.cwd(),
	registry: {
		fileName: `${process.cwd()}/src/element-registry.ts`,
		exportName: "ElementAttributes",
	},
});

try {
	await service.open("/project/src/profile.hbs", source);
	const items = await service.completions("/project/src/profile.hbs", sourceOffset);
	const hover = await service.hover("/project/src/profile.hbs", sourceOffset);
	const diagnostics = await service.diagnostics("/project/src/profile.hbs");
	await service.close("/project/src/profile.hbs");
} finally {
	await service.dispose();
}

LanguageServiceOptions includes:

  • projectRoot: root used for generated shadow-project paths and TypeScript startup;
  • registry: TypeFileReference naming the custom-element attribute registry;
  • context: one context reference or a callback that resolves a context per template;
  • shadowDirectory: generated-file directory, defaulting to .goldar under the project root;
  • tsconfigFileName: optional project configuration used by the TypeScript backend;
  • typescriptExecutable and compilerExecutable: explicit process paths;
  • backend and compiler: injectable TypeScriptBackend and TemplateCompilerBackend implementations, primarily for integrations and tests.

The service writes generated TypeScript shadow files and a shadow-project configuration. It owns and disposes both backends, including injected implementations.

open, change, and close manage document state. completions() returns CompletionItem values whose replacement ranges refer to the Handlebars source. hover() returns source-mapped Hover or undefined. diagnostics() merges compiler and TypeScript Diagnostic values and maps their ranges back to the template. Operations on unknown or closed documents throw.

Process backends

GoCompilerProcess.create(options?) owns a goldar-compiler child. Its compile(source, options?) returns a VirtualDocument; dispose() shuts down the process. GoCompilerProcessOptions accepts the compiler executable and working directory inherited from the compiler client.

TypeScript7ProcessBackend.create(options) owns a persistent TypeScript 7 tsc --lsp --stdio process rooted at projectRoot. TypeScript7BackendOptions requires that root and can select the TypeScript executable; the language service owns project configuration and supplies its generated shadow tsconfig. The class implements the full TypeScriptBackend document lifecycle and must be disposed.

TemplateCompilerBackend and TypeScriptBackend are extension contracts. A compiler returns a VirtualDocument plus mappings; a TypeScript backend consumes generated document URIs, zero-based LSP positions, and the minimal completion, hover, and diagnostic result shapes used by the service.

Virtual documents and source maps

The public model includes:

  • VirtualDocument and VirtualDocumentOptions;
  • tolerant TemplateDocument, TemplateFrontmatter, TemplateTag, TemplateAttribute, and TemplateAttributeValue syntax records;
  • CompilerDiagnostic and CompilerDiagnosticSeverity;
  • TypeRegistryReference and the optional marker ElementAttributes interface;
  • SourceMapping, MappingKind, MappingCapability, and MappingCapabilities;
  • TemplateSourceMap and OffsetRange.

SegmentSourceMap implements TemplateSourceMap. Its four methods map source/generated offsets and ranges while filtering by an operation capability. They return undefined when no capable mapping contains or overlaps the request. Zero-length mappings act as cursor anchors; overlapping mappings prefer the most specific applicable range.

Language server

startLanguageServer(streams?) creates and starts an LSP connection. With no streams it uses process stdin/stdout; embedded clients may pass LanguageServerStreams with readable input and writable output streams. The return value is the active connection.

Initialization options are supplied through the LSP initializationOptions object:

  • registryFile is required and resolved from the workspace root;
  • registryExport defaults to ElementAttributes;
  • contextExport, when supplied for a legacy project, loads that export from the sibling <template>.hbs.ts module when inline Props frontmatter is absent;
  • compilerExecutable selects the Go compiler.

A workspace root is required. The server keeps one compiler process and one TypeScript process per workspace, publishes merged diagnostics, and shuts them down with the connection lifecycle. The typed-handlebars-language-server binary is the stdio wrapper for editor clients.