Skip to content

Commit a8dd198

Browse files
eduwassjmstevers
andauthored
Updated TypeScript SDK (#984)
* bring in exsting work from: https://github.com/eduwass/datastar/tree/clean-pr-branch/sdk/typescript * Update TypeScript SDK: Move test servers files to enhance clarity, modify build process, and adjust tsconfig accordingly. * Update TypeScript SDK package.json: Add files section to include necessary directories and files for npm packaging. This way we exclude unnecessary example/test dirs from distribution. * rm leftover files * update .gitignored editor directories and files * Enhance README.md with structured notes for SDK usage and build process. Added emphasis on important notes regarding server commands and stream management. * Add migration plan for Datastar TypeScript SDK: outline key changes, migration tasks, and breaking changes. Implement 1.1: Update constants and types for new API specification, including renaming and restructuring of methods and parameters. * Implement Tasks 1.2 and 3.1 of Migration Plan 1.2 Abstract Class Core Changes 3.1 Add New Methods to Abstract Class * Complete Phase 2 implementation updates for serverSentEventGenerator in Node.js and Web SDK. Enhanced header handling, improved error validation, and ensured compliance with new specifications. Updated imports to use local Jsonifiable type. * Implements 3.2 Parameter Validation and Defaults Enhance validation in ServerSentEventGenerator: Implement checks for ElementPatchMode, required parameters, JSON format, and script attributes. Update migration plan to reflect verification of defaults and added validation methods. * Revise migration plan for Datastar TypeScript SDK: Update testing phases, including existing test updates and new test cases for specification compliance. Enhance documentation updates and build validation steps to align with recent changes in method names and parameter handling. * Refactor ServerSentEventGenerator: Remove ExecuteScript method and related validation logic. Update imports to remove file extensions. Bump version to 1.0.0-RC.12 and clean up unused constants in types and consts files. * Update examples and tests to use the latest Datastar release candidate version. Replace beta version references with the release candidate in Bun, Deno, and Node.js examples and tests. * Refactor imports in ServerSentEventGenerator and types files to include file extensions (deno compatibility). Update type definitions for responseInit and improve patch mode handling in validation logic. * Update eachNewlineIsADataLine method in ServerSentEventGenerator to add a space before each line prefix for improved formatting. * Update tests to use new spec methods. Refactors ServerSentEventGenerator tests to replace mergeFragments with PatchElements and update type imports for compatibility. Remove type-fest dependency from package.json and deno.lock. Fix line missing space. * Update package.json scripts for testing: change serve commands to point to test files instead of source files for Deno, Bun, and Node.js. * Update package version to 1.0.0-RC.12 in package.json * Refactor ServerSentEventGenerator methods: rename readSignals to ReadSignals and update related documentation and examples to reflect changes in signal handling and DOM updates. * Refactor examples to replace mergeFragments with PatchElements in Bun, Deno, and Node.js implementations for consistency with updated ServerSentEventGenerator methods. * Fix for compatiblity with new SDK test suite. * remove reference file * cleanup readme * remove outer mode from readme examples * Remove version edit Co-authored-by: Johnathan Stevers <[email protected]> * update version Co-authored-by: Johnathan Stevers <[email protected]> * Update sdk/typescript/examples/bun/package.json Co-authored-by: Johnathan Stevers <[email protected]> * Remove deepmerge-ts dependency, and refactor server-sent event generator to eliminate deepmerge usage. Update lock files accordingly. * Remove validateJson Co-authored-by: Johnathan Stevers <[email protected]> * Remove validateJson Co-authored-by: Johnathan Stevers <[email protected]> * use camelCase for ts sdk syntax and update readme * Ensure refactor method names to camelCase in TypeScript SDK, updating all relevant examples and documentation to use `readSignals` instead of `ReadSignals`. * Fix naming convention for DefaultpatchSignalsOnlyIfMissing to DefaultPatchSignalsOnlyIfMissing in consts.ts and types.ts for consistency. * Update script source URLs in TypeScript examples and tests. See: #984 (comment) * use main js bundle in tests too --------- Co-authored-by: Johnathan Stevers <[email protected]>
1 parent a7577f6 commit a8dd198

34 files changed

+1754
-521
lines changed

sdk/typescript/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ dist-ssr
1414

1515
# Editor directories and files
1616
.vscode/*
17+
.cursor/*
1718
!.vscode/extensions.json
1819
.idea
1920
.DS_Store

sdk/typescript/README.md

Lines changed: 238 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,96 +1,276 @@
1-
# TypeScript SDK for Datastar
21

3-
Implements the [SDK spec](../README.md) and exposes an abstract
4-
ServerSentEventGenerator class that can be used to implement runtime specific
5-
classes. NodeJS and web standard runtimes are currently implemented.
2+
<p align="center"><img width="200" height="200" src="https://data-star.dev/static/images/rocket-512x512.png"></p>
63

7-
Currently it only exposes an http1 server, if you want http2 I recommend you use
8-
a reverse proxy until http2 support is added.
4+
# Datastar TypeScript SDK
95

10-
Deno is used for building the npm package: `deno run -A build.ts VERSION`
6+
[![Version](https://img.shields.io/badge/version-1.0.0–RC.1-orange)](https://github.com/starfederation/datastar/releases) ![Static Badge](https://img.shields.io/badge/run_time-node_js-2a682d?logo=nodedotjs&labelColor=black) ![Static Badge](https://img.shields.io/badge/run_time-deno-6affaf?logo=deno&labelColor=black) ![Static Badge](https://img.shields.io/badge/run_time-bun-f672b6?logo=bun&labelColor=black)
117

12-
Usage is straightforward:
8+
A TypeScript SDK for building reactive web applications with [Datastar](https://github.com/starfederation/datastar).
9+
10+
Implements the [SDK spec](../README.md) and exposes an abstract ServerSentEventGenerator class that can be used to implement runtime specific classes. NodeJS and web standard runtimes are currently implemented.
11+
12+
Currently it only exposes an http1 server, if you want http2 I recommend you use a reverse proxy until http2 support is added.
13+
14+
## Features
15+
16+
- **Multi-runtime support**: Works with Node.js, Deno, and Bun
17+
- **TypeScript support**: Full type safety and IntelliSense
18+
19+
## Quick Start
20+
21+
### Installation & Import
22+
23+
**Node.js:**
24+
```bash
25+
npm install datastar-sdk
26+
```
27+
```javascript
28+
import { ServerSentEventGenerator } from "datastar-sdk/node";
29+
```
30+
31+
**Deno:**
32+
```typescript
33+
// No installation needed, import directly from npm
34+
import { ServerSentEventGenerator } from "npm:datastar-sdk/web";
35+
```
36+
37+
**Bun:**
38+
```bash
39+
bun add datastar-sdk
40+
```
41+
```javascript
42+
import { ServerSentEventGenerator } from "datastar-sdk/web";
43+
```
44+
45+
### Basic Usage
46+
47+
Here's a simple example in Node showing how to read client signals and send back element patches:
1348

1449
```javascript
15-
// this example is for node
50+
import { ServerSentEventGenerator } from "datastar-sdk/node";
51+
52+
// Read signals from the client request
1653
const reader = await ServerSentEventGenerator.readSignals(req);
1754

1855
if (!reader.success) {
19-
console.error('Error while reading signals', reader.error);
20-
res.end('Error while reading signals`);
21-
return;
22-
}
23-
24-
if (!('foo' in reader.signals)) {
25-
console.error('The foo signal is not present');
26-
res.end('The foo signal is not present');
56+
console.error('Error reading signals:', reader.error);
2757
return;
2858
}
2959

60+
// Stream updates back to the client
3061
ServerSentEventGenerator.stream(req, res, (stream) => {
31-
stream.mergeSignals({ foo: reader.signals.foo });
32-
stream.mergeFragments(`<div id="toMerge">Hello <span data-text="$foo">${reader.signals.foo}</span></div>`);
62+
// Patch signals
63+
stream.patchSignals(JSON.stringify({ foo: reader.signals.foo }));
64+
65+
// Patch DOM elements
66+
stream.patchElements(`<div id="toMerge">Hello <span data-text="$foo">${reader.signals.foo}</span></div>`);
3367
});
3468
```
3569

36-
The stream static method can receive an extra `options` object that can contain
37-
onError and onAbort callbacks as well as the keepalive option. The keepalive
38-
option will stop the stream from being closed once the onStart callback is
39-
finished. That means the user is responsible for ending the stream with
40-
`this.close()`.
70+
See examples for other runtimes below.
4171

4272
## Examples
4373

44-
Follow the links for more complete (and executable) examples
74+
### Runtime-Specific Examples
75+
76+
| Runtime | Example Location | How to Run | Try Online |
77+
|---------|-----------------|------------|------------|
78+
| **Node.js** | `examples/node/node.js` | [Instructions](examples/node/README.md) | [StackBlitz](https://stackblitz.com/edit/node-datastar) |
79+
| **Deno** | `examples/deno/deno.ts` | [Instructions](examples/deno/README.md) | [Val.town](https://www.val.town/x/eduwass/datastar-deno/code/main.tsx) |
80+
| **Bun** | `examples/bun/bun.ts` | [Instructions](examples/bun/README.md) | [Replit](https://replit.com/@eduwass/Bun-Datastar) |
4581

46-
- [NodeJS](./examples/node.js)
47-
- [Deno](./examples/deno.ts)
82+
Each example creates a simple web server demonstrating:
83+
- Signal handling from client requests
84+
- Element patching for DOM updates
85+
- Real-time communication via Server-Sent Events
4886

49-
## Frameworks / Alternate runtimes
87+
### Running Examples
5088

51-
If you can't simply use the node / web versions, then you can extend the
52-
abstract class in `./src/abstractServerSentEventGenerator.ts`. You will need to
53-
provide implementations of the `constructor`, `readSignals`, `stream` and `send`
54-
methods.
89+
1. Clone the repository
90+
2. Navigate to the specific example directory (e.g., `examples/node/`)
91+
3. Follow the instructions in the example's README file
92+
4. Visit `http://localhost:3000` in your browser
5593

56-
## Testing
94+
> [!NOTE]
95+
> 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.
5796
58-
A shell based testing suite is provided; see the [readme](../test/README.md) for
59-
more information.
97+
## API Reference
6098

61-
### Testing node
99+
### ServerSentEventGenerator
62100

63-
Start by building and running the node server
101+
The main class for handling Datastar communication.
64102

65-
```shell
66-
$ deno run -A build.ts xxx
67-
$ node ./npm/esm/node/node.js
103+
#### Static Methods
104+
105+
##### `readSignals(request)`
106+
Reads signals from a client request.
107+
108+
**Parameters:**
109+
- `request`: HTTP request object
110+
111+
**Returns:**
112+
```typescript
113+
{
114+
success: boolean;
115+
signals?: Record<string, any>;
116+
error?: string;
117+
}
68118
```
69119

70-
Then run the test suite
120+
##### `stream(request, response, callback, options?)`
121+
Creates a Server-Sent Event stream for real-time communication.
71122

72-
```shell
73-
$ cd ../test
74-
$ ./test-all.sh http://127.0.0.1:3000
75-
Running tests with argument: http://127.0.0.1:3000
76-
Processing GET cases...
77-
Processing POST cases...
123+
**Parameters:**
124+
- `request`: HTTP request object
125+
- `response`: HTTP response object
126+
- `callback`: Function that receives a stream instance
127+
- `options`: Optional configuration object
128+
129+
**Options:**
130+
```typescript
131+
{
132+
onError?: (error: Error) => void;
133+
onAbort?: () => void;
134+
keepalive?: boolean;
135+
}
78136
```
79137

80-
### Testing deno
138+
> [!IMPORTANT]
139+
> 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.
140+
141+
#### Stream Instance Methods
142+
143+
##### `patchSignals(signals, options?)`
144+
Patches signals into the client signal store.
81145

82-
Start by running the deno server
146+
**Parameters:**
147+
- `signals`: JSON string containing signal data to patch
148+
- `options`: Optional configuration object with `onlyIfMissing` boolean
83149

84-
```shell
85-
$ deno --allow-net ./src/web/deno.ts
150+
**Example:**
151+
```javascript
152+
stream.patchSignals(JSON.stringify({ foo: "bar", count: 42 }));
86153
```
87154

88-
Then run the test suite
155+
##### `patchElements(elements, options?)`
156+
Patches HTML elements into the client DOM.
157+
158+
**Parameters:**
159+
- `elements`: HTML string containing elements to patch
160+
- `options`: Optional configuration object with `mode` and `selector`
89161

90-
```shell
91-
$ cd ../test
92-
$ ./test-all.sh http://localhost:8000/
93-
Running tests with argument: http://localhost:8000/
94-
Processing GET cases...
95-
Processing POST cases...
162+
**Options:**
163+
- `mode`: Patch mode - "outer", "inner", "replace", "prepend", "append", "before", "after", "remove"
164+
- `selector`: CSS selector for targeting elements (required for some modes)
165+
- `useViewTransition`: Whether to use View Transition API
166+
167+
**Example:**
168+
```javascript
169+
stream.patchElements('<div id="myDiv">Updated content</div>');
96170
```
171+
172+
## Development
173+
174+
### Prerequisites
175+
176+
To develop or contribute to this SDK, you'll need:
177+
- [Deno](https://deno.land/) (primary development environment)
178+
- [Node.js](https://nodejs.org/) (for Node.js compatibility testing)
179+
- [Bun](https://bun.sh/) (for Bun compatibility testing)
180+
181+
### Building
182+
183+
Build the npm package:
184+
```bash
185+
deno run -A build.ts
186+
```
187+
188+
The above will pick the version from the [src/consts.ts](src/consts.ts) file. If you want to specify the version, use:
189+
```bash
190+
deno run -A build.ts VERSION
191+
```
192+
193+
> [!NOTE]
194+
> **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.
195+
196+
### Testing
197+
198+
#### Automated Testing
199+
200+
Run tests for all runtimes:
201+
```bash
202+
# Node.js
203+
npm run test-node
204+
205+
# Deno
206+
deno task test-deno
207+
208+
# Bun
209+
bun run test-bun
210+
```
211+
212+
#### Manual Testing
213+
214+
Start a development server:
215+
```bash
216+
# Node.js
217+
npm run serve-node
218+
219+
# Deno
220+
deno task serve-deno
221+
222+
# Bun
223+
bun run serve-bun
224+
```
225+
226+
Then run the test suite manually:
227+
```bash
228+
cd ../test
229+
./test-all.sh http://127.0.0.1:3000
230+
```
231+
232+
### Project Structure
233+
234+
```
235+
typescript/
236+
├── src/
237+
│ ├── node/ # Node.js-specific implementation
238+
│ ├── web/ # Web standards implementation (Deno/Bun)
239+
│ └── abstract/ # Abstract base classes
240+
├── examples/
241+
│ ├── node/ # Node.js example
242+
│ ├── deno/ # Deno example
243+
│ └── bun/ # Bun example
244+
└── test/ # Test suite
245+
```
246+
247+
## Runtime Support
248+
249+
### Node.js
250+
- Import: `datastar-sdk/node`
251+
- Requires: Node.js 18+
252+
- Uses Node.js-specific HTTP APIs
253+
254+
### Deno
255+
- Import: `npm:datastar-sdk/web`
256+
- Requires: Deno 1.30+
257+
- Uses Web Standards APIs
258+
259+
### Bun
260+
- Import: `datastar-sdk/web`
261+
- Requires: Bun 1.0+
262+
- Uses Web Standards APIs
263+
264+
## Custom Implementations
265+
266+
To support additional runtimes or frameworks, extend the abstract `ServerSentEventGenerator` class from `./src/abstractServerSentEventGenerator.ts`.
267+
268+
You'll need to implement:
269+
- `constructor`: Initialize runtime-specific components
270+
- `readSignals`: Parse signals from requests
271+
- `stream`: Create SSE streams
272+
- `send`: Send data to clients
273+
274+
The abstract class provides these public methods:
275+
- `patchElements(elements, options?)`: Patch HTML elements
276+
- `patchSignals(signals, options?)`: Patch signal data

sdk/typescript/build.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
// ex. scripts/build_npm.ts
22
import { build, emptyDir } from "@deno/dnt";
3+
import { VERSION } from "./src/consts.ts";
34

45
await emptyDir("./npm");
56

67
await build({
78
entryPoints: [
89
"./src/node/serverSentEventGenerator.ts",
910
"./src/web/serverSentEventGenerator.ts",
11+
"./test/node.ts",
1012
],
1113
outDir: "./npm",
1214
shims: {
@@ -16,7 +18,7 @@ await build({
1618
package: {
1719
// package.json properties
1820
name: "@starfederation/datastar-sdk",
19-
version: Deno.args[0],
21+
version: Deno.args[0] || VERSION,
2022
description: "Cross-runtime Javascript SDK for Datastar",
2123
license: "MIT",
2224
repository: {

sdk/typescript/bun.lockb

2.02 KB
Binary file not shown.

sdk/typescript/deno.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
{
22
"imports": {
33
"@deno/dnt": "jsr:@deno/dnt@^0.41.3"
4-
}
4+
},
5+
"tasks": {
6+
"check": "deno lint && deno check src/node/node.ts && deno check src/web/deno.ts && bun run --check src/web/bun.ts",
7+
"build": "deno run -A build.ts",
8+
"serve-deno": "deno run -A src/web/deno.ts",
9+
"test-deno": "./test/test-deno.sh"
10+
},
11+
"nodeModulesDir": "auto"
512
}

0 commit comments

Comments
 (0)