=begin pod

=NAME

Datastar SDK for Raku

=AUTHOR

E. Alvarez L<mail@alvar3z.com|mailto:mail@alvar3z.com>

=SYNOPSIS

=begin code :lang<raku>
use Datastar::SDK;

class MyRequest does RequestAdapter {
    method request-method(--> Str) { ... }
    method query-parameter(Str:D $name) { ... }
    method body-text(--> Str) { ... }
    method protocol-version(--> Str) { ... }
}

class MyResponse does ResponseAdapter {
    method set-header(Str:D $name, Str:D $value) { ... }
    method write(Str:D $chunk) { ... }
    method flush() { ... }
}

my $sse = ServerSentEventGenerator.new(
    request => $request,
    response => $response,
);

my %signals = read-signals($request);

$sse.patch-elements(
    '<section id="status">Saved</section>',
);

$sse.patch-signals(%(
    pending => False,
    error => JSON-NULL,
));
=end code

=DESCRIPTION

This is a data-oriented Datastar SDK written in Raku. The SDK implements the
Datastar SDK ADR with zero runtime dependencies. Raku++ is the primary compiler
used by this project to develop, test, and build it.

Install the distribution from the zef ecosystem:

=begin code :lang<sh>
zef install 'Datastar::SDK:auth<zef:ealvar3z>'
=end code

Then install the L<Raku++ compiler|https://github.com/ash/rakupp#install> to
run it with Raku++.

=SPECIFICATION

The core API follows Datastar's
L<SDK architecture decision record|https://github.com/starfederation/datastar/blob/develop/sdk/ADR.md>
and the constants, defaults, literals, and enums in the
L<v1 SDK configuration|https://github.com/starfederation/datastar/blob/develop/sdk/datastar-sdk-config-v1.json>.
The configuration's shape is described by its
L<JSON Schema|https://github.com/starfederation/datastar/blob/develop/sdk/datastar-sdk-config-v1.schema.json>.
Scoped view transitions use the ADR's newer C<viewTransitionSelector> option.

=ARCHITECTURE

The API follows this data-oriented flow:

=begin code
HTTP request adapter
  -> native Raku signals
  -> event hash
  -> SSE encoding
  -> HTTP response adapter
=end code

C<ServerSentEventGenerator> is the only stateful SDK object. It owns the
response lifecycle, serializes complete event writes with a C<Lock>, and
flushes after each event. Event constructors and JSON handling operate on
native Raku data.

=ADAPTERS

Implement the small C<RequestAdapter> and C<ResponseAdapter> roles for the HTTP
server used by the application. The synopsis shows the complete method
contracts.

For C<GET> and C<DELETE> requests, C<query-parameter> must return the
URL-decoded value of the requested query parameter. C<read-signals> asks for
the configured C<datastar> parameter and parses its JSON value. For C<POST>,
C<PUT>, and C<PATCH>, it parses C<body-text> directly.

=OPTIONS

Raku-style kebab-case option names correspond to the ADR's Go-style names:

=item C<event-id> corresponds to C<eventId>.

=item C<retry-duration> corresponds to C<retryDuration>.

=item C<use-view-transition> corresponds to C<useViewTransition>.

=item C<view-transition-selector> corresponds to C<viewTransitionSelector>.

=item C<only-if-missing> corresponds to C<onlyIfMissing>.

=item C<auto-remove> corresponds to C<autoRemove>.

C<patch-signals> accepts either native associative data or a JSON string. The
string form preserves formatting when multiline JSON must be streamed exactly.
Use the exported C<JSON-NULL> sentinel to retain JSON merge-patch removal values
inside native Raku data.

=EXAMPLES

The L<examples guide|https://github.com/ealvar3z/datastar-raku/tree/main/examples>
contains Raku ports of Datastar's Go examples:

=begin item
A Hello World server that streams a complete element for every message prefix.
=end item

=begin item
A zero-dependency hot-reload server driven by a long-lived SSE request.
=end item

Run either example from the repository root:

=begin code :lang<sh>
rakupp -Ilib -Iexamples/lib examples/helloworld/main.raku
rakupp -Ilib -Iexamples/lib examples/hotreload/main.raku
=end code

=TESTING

Run the unit tests from the repository root:

=begin code :lang<sh>
for test in t/*.rakutest; do rakupp -Ilib "$test"; done
RAKUPP_PARALLEL=1 rakupp -Ilib t/03-generator.rakutest
=end code

Run the conformance server from the repository root:

=begin code :lang<sh>
rakupp -Ilib t/conformance-server.raku
=end code

In another terminal:

=begin code :lang<sh>
go run github.com/starfederation/datastar/sdk/tests/cmd/datastar-sdk-tests@latest \
  -server http://127.0.0.1:7331 -v
=end code

Verify that the conformance server can be transpiled to native C++:

=begin code :lang<sh>
RAKULIB=lib rakupp --cpp t/conformance-server.raku >/dev/null
=end code

An exit status of C<0> means native code generation is available. Status C<5>
means C<--exe> would fall back to AOT or bundling.

Compile and run the native conformance server:

=begin code :lang<sh>
sdk_tmp=$(mktemp -d)
RAKULIB=lib \
  rakupp --exe t/conformance-server.raku \
  -o "$sdk_tmp/datastar-raku-conformance"
RAKULIB=lib "$sdk_tmp/datastar-raku-conformance"
=end code

The compile step must report C<Compiled (native)> without a fallback notice.
Run the same Go conformance command against the compiled server.

The conformance server is test-only. Production integrations should adapt the
roles to their HTTP stack so writes and flush errors propagate naturally.

=COPYRIGHT

Copyright 2026 E. Alvarez.

=LICENSE

This software is licensed under the
L<Artistic License 2.0|https://opensource.org/license/artistic-2-0>.

=end pod
