Skip to content

v0.36.0

Choose a tag to compare

@cuonggt cuonggt released this 02 Oct 02:30
· 22 commits to main since this release

The route list: tug routes prints every route of an app's, one a line: its method, path and name, the struct it takes, the file and line of the app's that added it, and its handler, as that line has it, wrappers and all. An app's routes were the lines its newApp adds them on, and tug gen wrote the named ones into routes.ts, but nothing listed them: which handler answers POST /login, what it takes, which routes a path has, and where each was added. A route's function, as Go names it, is often a wrapper's closure, main.newApp.(*app).guestsOnly.func15, which says nothing of the handler inside it; the line that added the route says it, and tug routes reads it there.

In an app made with tug new -auth at v0.36.0, which has 50 routes:

$ tug routes login
METHOD  PATH                    NAME                    TAKES                    ADDED        HANDLER
GET     /login                  login                                            main.go:391  a.guestsOnly(loginPage)
POST    /login                  login.store             LoginInput               main.go:392  a.guestsOnly(a.login)
POST    /login/passkey          login.passkey           PasskeyInput             main.go:394  a.guestsOnly(a.passkeyLogin)
POST    /login/passkey/options  login.passkey.options                            main.go:393  a.guestsOnly(a.passkeyLoginOptions)
GET     /two-factor-challenge   two-factor.login                                 main.go:395  a.guestsOnly(twoFactorChallengePage)
POST    /two-factor-challenge   two-factor.login.store  TwoFactorChallengeInput  main.go:396  a.guestsOnly(a.twoFactorChallenge)

and POST /login as tug routes -json writes it, for a script:

{
  "method": "POST",
  "path": "/login",
  "name": "login.store",
  "handler": "a.guestsOnly(a.login)",
  "function": "main.newApp.(*app).guestsOnly.func15",
  "takes": "LoginInput",
  "file": "main.go",
  "line": 392
}

What's new:

  • tug routes: builds the app and runs it, as tug gen does, and prints its routes, by path, then method, in columns: METHOD, PATH, NAME, TAKES, the struct the route Takes, ADDED, the file and line of the app's that added it, and HANDLER, last, as its width varies most.
  • Every route of the app's: named or not, as /up, a group's, and one of any method, as ANY; not tug's own, as the misses' catch-all, or the endpoints of Inertia's DevTools.
  • The handler as the app wrote it: read with go/parser from the line that added the route, the innermost of the router's calls over it, so a route added over several lines is read whole, and printed on one line, a function literal without its body. A route a helper of the app's adds, whose line gives the helper's own variable, is listed by its function's name, at the helper's line.
  • A filter: tug routes login lists the routes whose path or name has login in it, in any case; a text no route has is an error.
  • -json: the same as JSON, with the handler's function, as Go names it, beside its expression.
  • The routes the app has as it runs: the ones main adds as it starts, with the app's .env, from the run tug gen and tug lang make, without the database, which tug.Generating leaves out. A route the environment leaves out, as the auth starter's /files without a disk of its own, is left out here too.
  • The guide: CLI, tug routes; Routing, a pointer to it; and the README.

Upgrading: nothing an app calls changed: go get github.com/cuonggt/tug@v0.36.0, and go install github.com/cuonggt/tug/cmd/tug@v0.36.0 for the CLI. The app lists its routes itself, in the run tug gen makes, so tug routes needs the app on v0.36.0: one on an older tug says "the app has no routes". tug gen writes the same types as before, and an app's tests pass as they did.

The guide is in docs/. tug needs Go 1.26.