Skip to content

Commit

Permalink
feat: preact pivot (#8)
Browse files Browse the repository at this point in the history
  • Loading branch information
LeeCheneler authored Nov 18, 2024
1 parent cd9ce74 commit 121b256
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 38 deletions.
2 changes: 0 additions & 2 deletions .npm/react-dom.ts

This file was deleted.

2 changes: 0 additions & 2 deletions .npm/react-dom/server.ts

This file was deleted.

4 changes: 0 additions & 4 deletions .npm/react.ts

This file was deleted.

81 changes: 61 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Mage

Simple, composable APIs and web apps for Deno.
Build web applications with [Deno](https://deno.com) and
[Preact](https://preactjs.com).

## Installation

Expand Down Expand Up @@ -41,7 +42,7 @@ app.get("/render", async (context) => {
app.run({
port: 8000,
onListen({ hostname, port }) {
console.log(`Listening on ${hostname}:${port}`);
console.log(`Listening on http://${hostname}:${port}`);
},
});
```
Expand Down Expand Up @@ -81,28 +82,63 @@ A collection of prebuilt middleware is available to use.

## Context

The context object is passed to each middleware and contains details about the
request and response.
A context object is passed to each middleware.

### Url

The URL is parsed and placed on the context.

```tsx
app.post("/", async (context) => {
console.log(context.url);
console.log(context.request.method
console.log(context.request.headers.get("Content-Type"));
console.log(await context.request.text());
});
context.url.pathname
context.url.searchParams
...
```

### Request

The request object is available on the context.

```tsx
context.request.method
context.request.headers.get("Content-Type")
await context.request.text()
...
```

Additionally it contains utility functions to respond to the request.
### Response

The response object is available on the context.

```tsx
context.response.headers.set("Content-Type", "text/plain");
context.response.headers.delete("Content-Type", "text/plain");
```

### Response utilities

A number of utility methods are available to configure the response content.

#### `context.text(...)`

Respond with text.

```tsx
// Text response
context.text(StatusCode.OK, "Hello, World!");
```

// JSON response
#### `context.json(...)`

Respond with JSON.

```tsx
context.json(StatusCode.OK, { message: "Hello, World!" });
```

#### `context.render(...)`

// Render JSX to HTML response
Render JSX to HTML using [Preact](https://preactjs.com).

```tsx
await context.render(
StatusCode.OK,
<html lang="en">
Expand All @@ -111,19 +147,24 @@ await context.render(
</body>
</html>,
);
```

#### `context.empty(...)`

Respond with an empty response, useful for response like `204 No Content`.

```tsx
// Empty response
context.empty(StatusCode.NoContent);

// Redirect
context.redirect(RedirectType.Permanent, "/new-location");
```

You can also configure headers for the response:
#### `context.redirect(...)`

Redirect the request to another location.

```tsx
context.response.headers.set("Content-Type", "text/plain");
context.response.headers.delete("Content-Type", "text/plain");
// Redirect
context.redirect(RedirectType.Permanent, "/new-location");
```

## Routing
Expand Down
8 changes: 3 additions & 5 deletions deno.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,11 @@
"imports": {
"@std/expect": "jsr:@std/expect@^1.0.8",
"@std/testing": "jsr:@std/testing@^1.0.5",
"@types/react": "npm:@types/[email protected]",
"@types/react-dom": "npm:@types/[email protected]",
"react": "npm:react@^18.3.1",
"react-dom": "npm:react-dom@^18.3.1"
"preact": "npm:[email protected]",
"preact-render-to-string": "npm:[email protected]"
},
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "react"
"jsxImportSource": "preact"
}
}
2 changes: 1 addition & 1 deletion example-app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,6 @@ app.get("/render", async (context) => {
app.run({
port: 8000,
onListen({ hostname, port }) {
console.log(`Listening on ${hostname}:${port}`);
console.log(`Listening on http://${hostname}:${port}`);
},
});
9 changes: 5 additions & 4 deletions src/context.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type React from "../.npm/react.ts";
import { renderToReadableStream } from "../.npm/react-dom/server.ts";
import type { VNode } from "preact";
import { renderToStringAsync } from "preact-render-to-string";
import { RedirectType, StatusCode, statusTextMap } from "./http.ts";
import type { MageRouter } from "./router.ts";

Expand Down Expand Up @@ -68,8 +68,9 @@ export class MageContext {
* @param status
* @param body
*/
public async render(status: StatusCode, body: React.ReactNode) {
this.response = new Response(await renderToReadableStream(body), {
public async render(status: StatusCode, body: VNode) {
const html = await renderToStringAsync(body);
this.response = new Response(`<!DOCTYPE html>${html}`, {
status: status,
statusText: statusTextMap[status],
headers: this.response.headers,
Expand Down

0 comments on commit 121b256

Please sign in to comment.