Crolite: filling the "Mojolicious::Lite" gap in the Cro ecosystem

Crolite: filling the "Mojolicious::Lite" gap in the Cro ecosystem


Introduction

When I start something new in Raku with Cro, I almost always begin with a mental sketch: two or three routes, a response shape, maybe a typed segment. In the Perl world I leaned heavily on Mojolicious::Lite for that prototyping phase. In Cro—powerful and modular as it is—I missed an immediate “lite mode”: no manual wiring of server, pipeline, and router just to test a thought. Out of that friction came Crolite: a thin layer that re‑exports Cro’s routing keywords and adds a multi MAIN with quick exploration commands.

What Crolite Is

  • Goal: Make minimal HTTP prototypes trivial while ideas mature.
  • Approach: Reuse Cro’s router directly; no new DSL.
  • Deliverable: A collected RouteSet + a tiny embedded CLI.
  • Philosophy: “Start now; graduate later to a full Cro app.”

Installation

From a local checkout (inside the project directory):

zef install .

Once published:

zef install Crolite

First Example

File example.raku:

use Crolite;

get -> $any {
    content 'text/plain', "Hello: $any";
}

delete -> 'thing', Int $id {
    content 'application/json', %( :$id );
}

List derived routes:

raku example.raku routes

Run a development server:

raku example.raku daemon --host=127.0.0.1 --port=3000

Test a route without a persistent daemon (ephemeral in‑memory request):

raku example.raku GET /thing/42

Suggested Workflow

  1. Sketch routes and response formats.
  2. Run raku app.raku routes to confirm patterns.
  3. Fire single requests: raku app.raku GET /foo/123.
  4. Iterate until it stabilizes.
  5. Promote to a full Cro project if you need richer middleware, structured logging, TLS, etc.

CLI Options

CommandPurpose
routesPrint summary of registered endpoints
daemon [--host=0.0.0.0] [--port=10000]Start simple Cro server
GET <path>Single in‑memory GET
POST <path>Single POST (no custom body)
PUT <path>Single PUT
DELETE <path>Single DELETE
http <path> --method=<VERB>Generic form for any method

Stop the daemon with Ctrl+C (SIGINT is trapped for graceful shutdown).

Dynamic Segments & Typing

use Crolite;

get -> 'greet', Str $name {
    content 'text/plain', "Hi $name!";
}

post -> 'sum', Int $a, Int $b {
    content 'application/json', %( total => $a + $b );
}

Test:

raku app.raku GET /greet/Ana
raku app.raku POST /sum/2/5

Returning JSON

Just produce a Hash or Map:

get -> 'status' {
    content 'application/json', %( service => 'ok', ts => DateTime.now );
}

Hooks (Before / After)

If you manually add before or after handlers to the underlying RouteSet, Crolite includes them when composing the application for daemon:

use Crolite;

$*CRO-ROUTE-SET.before: {
    # Simple logging / auth stub
    proceed;
}

get -> 'ping' { content 'text/plain', 'pong' }

More Complete Example

use Crolite;

get -> 'health' {
    content 'application/json', %( ok => True );
}

put -> 'echo', Str $msg {
    content 'text/plain', $msg.uc;
}

post -> 'calc', Int $x, Int $y {
    content 'application/json', %( sum => $x + $y, prod => $x * $y );
}

delete -> 'soft', Int $id {
    content 'application/json', %( deleted => $id, soft => True );
}

Quick ping:

raku app.raku GET /health

Server:

raku app.raku daemon --port=4000

Ergonomics While Prototyping

  • Rapid changes: Save & re‑run; no auto‑reloader (yet).
  • Inspection: routes surfaces path typos immediately.
  • Atomic requests: Avoids opening another terminal for curl just to see a body.

Current Limitations

  • No structured logging out of the box.
  • No built‑in TLS / websockets / streaming presets.
  • No hot reload.
  • Experimental API (may shift).

When to Migrate to a Full Cro App

  • You need chained middleware (auth, tracing, rate limiting).
  • You require richer body parsing / serialization customization.
  • You integrate multiple services or supervised components.
  • You need observability (metrics, distributed tracing, advanced logs).

Possible Future Roadmap

  • Optional reload in daemon mode.
  • Alternate tabular output for routes.
  • Lightweight latency / metrics helper.
  • Test skeleton generator for promotion phase.

Quick Testing Tips

  • Use the embedded CLI to validate the contract before formal tests.
  • When formalizing, reuse Cro::HTTP::Test (mirrors what the CLI verbs do).

Wrapping Up

Crolite does not compete with the full flexibility of a structured Cro project; it lowers the time to first useful response when exploring HTTP ideas in Raku. If you also miss the lightness of Mojolicious::Lite, try making the first step of each spike just:

use Crolite;

Then, once the shape hardens, graduate to something more robust.

Suggestions, issues, and PRs welcome.



Source link

Leave a Reply

Your email address will not be published. Required fields are marked *