A TypeScript SDK for building reactive web applications with Datastar.
Implements the SDK spec and exposes an abstract ServerSentEventGenerator class that can be used to implement runtime specific classes. NodeJS and web standard runtimes are currently implemented.
Currently it only exposes an http1 server, if you want http2 I recommend you use a reverse proxy until http2 support is added.
- Multi-runtime support: Works with Node.js, Deno, and Bun
- TypeScript support: Full type safety and IntelliSense
Node.js:
npm install @starfederation/datastar-sdk
import { ServerSentEventGenerator } from "@starfederation/datastar-sdk/node";
Deno:
// No installation needed, import directly from npm
import { ServerSentEventGenerator } from "npm:@starfederation/datastar-sdk/web";
Bun:
bun add @starfederation/datastar-sdk
import { ServerSentEventGenerator } from "@starfederation/datastar-sdk/web";
Here's a simple example in Node showing how to read client signals and send back element patches:
import { ServerSentEventGenerator } from "@starfederation/datastar-sdk/node";
// Read signals from the client request
const reader = await ServerSentEventGenerator.readSignals(req);
if (!reader.success) {
console.error('Error reading signals:', reader.error);
return;
}
// Stream updates back to the client
ServerSentEventGenerator.stream(req, res, (stream) => {
// Patch signals
stream.patchSignals(JSON.stringify({ foo: reader.signals.foo }));
// Patch DOM elements
stream.patchElements(`<div id="toMerge">Hello <span data-text="$foo">${reader.signals.foo}</span></div>`);
});
See examples for other runtimes below.
Runtime | Example Location | How to Run | Try Online |
---|---|---|---|
Node.js | examples/node/node.js |
Instructions | StackBlitz |
Deno | examples/deno/deno.ts |
Instructions | Val.town |
Bun | examples/bun/bun.ts |
Instructions | Replit |
Each example creates a simple web server demonstrating:
- Signal handling from client requests
- Element patching for DOM updates
- Real-time communication via Server-Sent Events
- Clone the repository
- Navigate to the specific example directory (e.g.,
examples/node/
) - Follow the instructions in the example's README file
- Visit
http://localhost:3000
in your browser
Note
The npm run serve-*
and deno task serve-*
commands in the root directory are for SDK development and testing, not for running the user examples.
The main class for handling Datastar communication.
Reads signals from a client request.
Parameters:
request
: HTTP request object
Returns:
{
success: boolean;
signals?: Record<string, any>;
error?: string;
}
Creates a Server-Sent Event stream for real-time communication.
Parameters:
request
: HTTP request objectresponse
: HTTP response objectcallback
: Function that receives a stream instanceoptions
: Optional configuration object
Options:
{
onError?: (error: Error) => void;
onAbort?: () => void;
keepalive?: boolean;
}
Important
When keepalive: true
is set, the stream will not be closed automatically after the callback finishes. You are responsible for calling stream.close()
to end the stream.
Patches signals into the client signal store.
Parameters:
signals
: JSON string containing signal data to patchoptions
: Optional configuration object withonlyIfMissing
boolean
Example:
stream.patchSignals(JSON.stringify({ foo: "bar", count: 42 }));
Patches HTML elements into the client DOM.
Parameters:
elements
: HTML string containing elements to patchoptions
: Optional configuration object withmode
andselector
Options:
mode
: Patch mode - "outer", "inner", "replace", "prepend", "append", "before", "after", "remove"selector
: CSS selector for targeting elements (required for some modes)useViewTransition
: Whether to use View Transition API
Example:
stream.patchElements('<div id="myDiv">Updated content</div>');
Removes elements from the client DOM by selector or by HTML string with IDs.
Parameters:
selector
: CSS selector for elements to remove (optional; mutually exclusive with elements)elements
: HTML string of elements with IDs to remove (optional; required if selector is not provided)options
: Optional configuration object witheventId
,retryDuration
Examples:
// Remove by selector
stream.removeElements('#feed, #otherid');
// Remove by HTML elements with IDs
stream.removeElements(undefined, '<div id="first"></div><div id="second"></div>');
Removes one or more signals from the client signal store.
Parameters:
signalKeys
: The signal key or array of keys to removeoptions
: Optional configuration object withonlyIfMissing
,eventId
,retryDuration
Examples:
// Remove a single signal
stream.removeSignals('foo');
// Remove multiple signals
stream.removeSignals(['foo', 'bar']);
Executes a script on the client by sending a <script> tag via SSE.
Parameters:
script
: The JavaScript code to executeoptions
: Optional configuration object:autoRemove
: If true (default), adds data-effect="el.remove()" to the script tagattributes
: Object of script tag attributes (preferred)eventId
,retryDuration
Examples:
// Execute a simple script
stream.executeScript('console.log("Hello from server!")');
// Execute a script and keep it in the DOM
stream.executeScript('alert("Persistent!")', { autoRemove: false });
// Execute with custom attributes (object form preferred)
stream.executeScript('doSomething()', { attributes: { type: "module", async: "true" } });
To develop or contribute to this SDK, you'll need:
- Deno (primary development environment)
- Node.js (for Node.js compatibility testing)
- Bun (for Bun compatibility testing)
- Go (required for running the Go test suite)
Build the npm package:
deno run -A build.ts
The above will pick the version from the src/consts.ts file. If you want to specify the version, use:
deno run -A build.ts VERSION
Note
For Developers: The build process includes test files in the npm/
directory for local testing, but they are excluded from the published npm package via .npmignore
. Test files are built into npm/esm/test/
and npm/script/test/
directories to support the test scripts (npm run test-node
, etc.), but these directories are not included when publishing to the npm registry.
To run all tests for Node.js, Deno, and Bun (mirroring CI):
bash test/run-all.sh
- This script will:
- Check for required tools (
deno
,node
,bun
,go
,git
) - Clone or update the core datastar repo for test files (in
/datastar/
, which is gitignored) - Build the SDK
- Start test servers for each runtime
- Run the Go test suite against each server
- Print results and logs
- Check for required tools (
Note: This is the same script used by GitHub Actions for CI.
typescript/
├── src/ # SDK source code
│ ├── node/ # Node.js-specific implementation
│ ├── web/ # Web standards implementation (Deno/Bun)
│ └── abstract/ # Abstract base classes
├── examples/ # Example apps for each runtime
│ ├── node/
│ ├── deno/
│ └── bun/
├── test/ # Unified test runner and test entrypoints
└── datastar/ # (gitignored) Cloned core repo for Go test files (used by test/run-all.sh)
- Import:
@starfederation/datastar-sdk/node
- Requires: Node.js 18+
- Uses Node.js-specific HTTP APIs
- Import:
npm:@starfederation/datastar-sdk/web
- Requires: Deno 1.30+
- Uses Web Standards APIs
- Import:
@starfederation/datastar-sdk/web
- Requires: Bun 1.0+
- Uses Web Standards APIs
To support additional runtimes or frameworks, extend the abstract ServerSentEventGenerator
class from ./src/abstractServerSentEventGenerator.ts
.
You'll need to implement:
constructor
: Initialize runtime-specific componentsreadSignals
: Parse signals from requestsstream
: Create SSE streamssend
: Send data to clients
The abstract class provides these public methods:
patchElements(elements, options?)
: Patch HTML elementspatchSignals(signals, options?)
: Patch signal dataremoveElements(selector?, elements?, options?)
: Remove elements by selector or HTML stringremoveSignals(signalKeys, options?)
: Remove one or more signalsexecuteScript(script, options?)
: Execute a script on the client