tako docs guide reference api
GitHub

tako gen client ts — the generated TypeScript client

Declare

Nothing to declare — every browser-callable tako.API endpoint is in; the command reads the app:

tako gen client ts [--out <path>]

Default output is .tako/gen/client/ts/api.ts; --out puts it where your frontend wants it. Output is deterministic — the same code produces a byte-identical file — so commit it and let a test pin its freshness (shop does; see below). In examples/shop/app.go:

$ tako gen client ts --out web/src/api.ts
  client   web/src/api.ts — 7 endpoints, 7 types
           excluded: billing.Charge POST /charge — private (IAM-only — browsers cannot mint OIDC)

Exclusion is never silent — the reasons land in the generated header:

// Code generated by tako gen client ts. DO NOT EDIT.
//
// Typed client for the api endpoints of shop: plain fetch, zero
// dependencies. The session cookie rides every call (same-origin);
// non-GET requests attach X-CSRF-Token from the page's meta tag.
//
// Excluded (not browser-callable):
//   billing.Charge POST /charge — private (IAM-only — browsers cannot mint OIDC)

Three things get excluded: Route.Private ("browsers cannot mint OIDC"), multipart uploads ("the signed-URL flow, not the JSON client"), and form-bound endpoints ("browsers post forms to it directly").

Use

One typed method per endpoint — path params are positional args, the JSON body an interface carrying your own type name, query params one trailing optional object. Non-2xx throws ApiError with the status and the message from tako's {"error": ...} body. From examples/shop/web/src/app.ts:

import { createClient, ApiError, Product, Order } from "./api";

const api = createClient();

const order = await api.placeOrder({ productId: p.id, qty: 1 });
} catch (e) {
  if (e instanceof ApiError && e.status === 401) {
    location.assign("/_tako/signin?next=/");
    return;
  }

createClient({baseUrl, headers}): baseUrl targets a deployed service (default same-origin); headers ride every call — non-browser callers pass the session cookie here.

Local

The recommended loop: change the api, regenerate, and let your frontend toolchain typecheck the result — shop's SiteConfig.Build esbuild step bundles app.ts against the committed client, so signature drift is a frontend build error. The client is a zero-dependency ES module: no tako needed in frontend builds — just a committed file.

Cloud

Nothing extra deploys. In the browser the session cookie rides every call and non-GET requests attach X-CSRF-Token from the page's meta tag; from outside a browser, pass baseUrl and the session cookie via headers (mint one with the curl recipe in validate/shop.md).

Test it

Shop's examples/shop/api_test.go pins the committed client to the generator's output — drift cannot merge:

if !bytes.Equal(content, committed) {
    t.Fatal("web/src/api.ts is stale — regenerate: tako gen client ts --out web/src/api.ts")
}

Errors you'll meet

Generation failures are analyzer-style diagnostics with file:line:

Not yet