Skip to content

TypeScript client

Package: @eelgrass/client (clients/typescript).

Export paths

ImportRole
@eelgrass/clienteelgrass tagged template, EelgrassQuery, EelgrassParam, EelgrassExecutor
@eelgrass/client/moneyMoney class
@eelgrass/client/shapeTypecheck JSON contract (EelgrassType, EelgrassShape, decode)
@eelgrass/client/codegenEscape-hatch tagged-template codegen (generateTypes)
@eelgrass/client/named-codegenNamed-query codegen (generateNamedQueryModules)
@eelgrass/client/configeelgrass.config.json parse + glob helper (parseConfig, DEFAULT_CONFIG)

CLI bin: eelgrass-codegen.

Preferred path: named queries

  1. Write schemas + named queries as .eel
  2. Run eelgrass-codegen --config eelgrass.config.json
  3. Import generated functions; pass them to an EelgrassExecutor
ts
import { GetPaid } from "./generated/users.queries";
import { Money } from "@eelgrass/client/money";

const rows = await exec.execute(
  GetPaid({ min_balance: Money.minor(50_00n, "USD") }),
);
// rows typed from the query's select shape

Money constructors that exist today:

ts
import { Money } from "@eelgrass/client/money";

Money.minor(4999n, "USD");     // minor units (cents)
Money.parse("49.99", "USD");   // decimal string only. Not a number.

There is no Money.usd. Cross-currency arithmetic is rejected at runtime. Same doctrine as the language.

See Named queries and Examples (examples/eelgrass.config.json).

Config

eelgrass.config.json fields (@eelgrass/client/config):

FieldMeaningDefault
schemasSchema .eel paths (merged in order)["schemas.eel"]
queriesGlob(s) for named-query .eel files["src/queries/**/*.eel"]
outDirGenerated TypeScript modules"src/generated"
moneyImportOptional Money import path override@eelgrass/client/money

Codegen shells out to the eelgrass binary (typecheck-queries). Set EELGRASS_BINARY if it is not on PATH.

Escape hatch

ts
import { eelgrass } from "@eelgrass/client";
import type { EelgrassExecutor, EelgrassQuery } from "@eelgrass/client";

const q: EelgrassQuery = eelgrass`users |> select { id, name }`;
// await exec.execute(q)

Tagged-template codegen (legacy):

bash
eelgrass-codegen <schemas.eel> <output.ts> <src1.ts> [src2.ts ...]

Use for one-offs and tests. Prefer named queries for day-to-day app work. Until a build plugin lands, the bare eelgrass…`` template returns EelgrassQuery with result types defaulting to unknown[] unless escape-hatch codegen wraps them.

EelgrassExecutor

ts
interface EelgrassExecutor {
  execute<TRows>(
    q: EelgrassQuery<TRows>,
    opts?: { tenant?: string },
  ): Promise<TRows[]>;
  atomic<TRowses extends unknown[]>(
    qs: { [K in keyof TRowses]: EelgrassQuery<TRowses[K]> },
    opts?: { tenant?: string },
  ): Promise<TRowses>;
}

Transport reality

EelgrassExecutor is the contract. A shipping HTTP/IPC driver is not in the package yet. Today you:

  • drive the engine via eelgrass run / Studio / wasm ABI, or
  • implement EelgrassExecutor against eelgrass serve's /query for experiments.

See Status.

Pre-alpha. Local-first. Stdlib-only Rust engine. Tenant concerns shifted left into the database.