Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: CI

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: "20"

- name: Install Bun
uses: oven-sh/setup-bun@v2

- name: Install dependencies
run: npm ci

- name: Typecheck
run: bun run typecheck

- name: Test
run: bun test
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# master

# 1.2.0

- TypeScript: Add first-class support and typings for TS/TSX usage.
- Ship `.d.ts` for JSX runtime (`Hjsx`) and SSR (`H`).
- Add `.d.ts` for `Handlers` and `RequestController` (server APIs).
- Add `.d.ts` for `Client` (actions + validity messages) and `FormDataHelpers`.
- Add stub `.d.ts` for `ResXClient` (browser script with no exports).
- Docs: Update TypeScript guide to use `jsxImportSource: "rescript-x"`.
- Tests: Add TypeScript tests for TSX rendering, fragments, handlers, client actions, validity messages, and form data helpers.

# 1.1.0

- First class CSRF protection with `Bun.CSRF` tokens.
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,8 @@ You can now start up the dev environment: `bun run dev`. Open up `localhost:9000

There's a ton more to ResX of course, but this should get you started.

> TypeScript users: See the dedicated guide in [TYPESCRIPT.md](./TYPESCRIPT.md) for JSX setup and examples.

### Routing

As you noticed from the example above, there's no explicit router in ResX itself. In the future, we might ship a dedicated type safe router in the style of [rescript-relay-router](https://github.com/zth/rescript-relay-router). But for now, we'll use pattern matching!
Expand Down Expand Up @@ -1009,3 +1011,7 @@ This section will be expanded as we go along.
- Relay for ResX
- Static and semi-static generation
- Suspense and (out of order) streaming

## Future

- Use branded types where ReScript uses abstract types, to get more type safety
72 changes: 72 additions & 0 deletions TYPESCRIPT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# TypeScript with ResX

This guide shows how to use ResX from TypeScript, including TSX-based JSX.

## Setup JSX with TypeScript

ResX ships `.d.ts` for its JSX runtime (`Hjsx`) and SSR (`H`). To author TSX:

1. Install TypeScript in your project (consumer app):

```bash
npm i -D typescript
```

2. Configure your `tsconfig.json`:

```json
{
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "rescript-x",
"module": "ESNext",
"moduleResolution": "Bundler",
"target": "ES2022",
"lib": ["ES2022", "DOM"]
}
}
```

3. Write TSX using ResX JSX runtime and render it via `H`:

```tsx
// example.tsx
import * as H from "rescript-x/H";

function Page() {
return <div class="p-4">Hello from TSX + ResX!</div>;
}

async function renderHtml() {
return await H.renderToString(<Page />);
}
```

4. Use with Bun server and ResX handlers:

```ts
// server.ts
import {
make as makeHandlers,
handleRequest,
} from "rescript-x/Handlers";
import * as H from "rescript-x/H";

const handlers = makeHandlers(async (_req) => ({}));

Bun.serve({
port: 4444,
async fetch(request) {
return handleRequest(handlers, {
request,
render: async () => <div>Hello ResX + TS</div>,
});
},
});
```

Notes:

- You can import ResX modules directly, e.g. `rescript-x/Handlers` (no `/src` prefix needed).
- The JSX runtime is provided by the package export `rescript-x/jsx-runtime`, so set `jsxImportSource` to `"rescript-x"`.
- Elements and props are intentionally permissive for flexibility; you can layer your own prop typing per component as desired.
26 changes: 26 additions & 0 deletions demo-ts/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# ResX TypeScript Demo

A minimal, TypeScript-only example showing how to build a ResX app with TSX.

## Scripts

- `bun install` — install dependencies
- `bun run dev:server` — start Bun server on http://localhost:4444
- `bun run dev:vite` — start Vite dev server on http://localhost:9000

Open http://localhost:9000 in your browser. The Vite plugin proxies dynamic routes to the Bun server and serves assets from `assets/`.

## Files

- `tsconfig.json` — configured for TSX via `jsxImportSource: "rescript-x"`
- `vite.config.ts` — uses the ResX Vite plugin
- `assets/styles.css` — sample CSS
- `src/Html.tsx` — outer HTML shell, includes HTMX + ResX client scripts
- `src/pages/Home.tsx` — page component using HTMX + Client actions
- `src/server.ts` — Bun server + ResX handlers

## Notes

- The Vite plugin generates `src/__generated__/res-x-assets.js` in dev; `Html.tsx` imports it when available to reference the ResX client bundle path. If it's not yet generated, it falls back to `/node_modules/rescript-x/src/ResXClient.js` in dev.
- For production builds, run `bun run build` to build the asset bundle; serve `dist/` with your preferred static file server alongside your Bun server.

7 changes: 7 additions & 0 deletions demo-ts/assets/styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/* Demo styles */
body { font-family: system-ui, -apple-system, Segoe UI, Roboto, sans-serif; }
.wrap { padding: 2rem; }
.box { padding: 1rem; border: 1px solid #ccc; border-radius: 8px; background: #fafafa; }
.btn { padding: 0.5rem 0.75rem; border: 1px solid #222; border-radius: 6px; }
.mt-2 { margin-top: 0.5rem; }

Loading
Loading