# AbsoluteJS

Full‑stack, **type‑safe** batteries‑included platform that lets you **server‑side render _any_ modern front‑end**—React, Svelte, plain HTML, HTMX (Vue & Angular coming)—with a single Bun‑powered build step.

[![bun-required](https://img.shields.io/badge/runtime-bun%401.x-yellowgreen?logo=bun)](https://bun.sh)
[![elysia-required](https://img.shields.io/badge/server-elysia%40latest-blue?logo=elysia)](https://elysiajs.com)
![license](https://img.shields.io/badge/license-BSL--1.1-lightgrey)

---

## Why Absolute JS?

- **Universal SSR.** Bring your favourite UI layer; Absolute JS handles bundling, hydration, and HTML streaming.
- **One build, one manifest.** Call `build()` once—get a manifest mapping every page’s client and server assets, ready to wire into routes.
- **End‑to‑end type safety.** A unified source of truth for your types—from the database, through the server, and all the way to the client—so you can be certain of the data shape at every step.
- **Zero‑config philosophy.** Point the build at your folders; sane defaults light up everything else.
- **Plugin power.** Extend with standard Elysia plugins—ship auth, logging, i18n, and more. First‑party: `absolute-auth`, `networkingPlugin`.

---

## Requirements

| Tool       | Version | Purpose                                     |
| ---------- | ------- | ------------------------------------------- |
| **Bun**    | ≥ 1.2   | Runtime, bundler, and TypeScript transpiler |
| **Elysia** | latest  | Web server & middleware platform            |

---

## Installation

```bash
bun add @absolutejs/absolute
```

---

## Quick Start

```ts
// example/server.ts
import { staticPlugin } from '@elysiajs/static';
import { Elysia } from 'elysia';
import { file } from 'bun';
import { build } from 'absolutejs/core/build';
import {
	handleHTMLPageRequest,
	handleSveltePageRequest
} from 'absolutejs/core/pageHandlers';
import { handleReactPageRequest } from 'absolutejs/react';

import { ReactExample } from './react/pages/ReactExample';
import SvelteExample from './svelte/pages/SvelteExample.svelte';
import { networkingPlugin } from 'absolutejs';

const manifest = await build({
	assetsDirectory: 'example/assets',
	buildDirectory: 'example/build',
	htmlDirectory: 'example/html',
	htmxDirectory: 'example/htmx',
	reactDirectory: 'example/react',
	svelteDirectory: 'example/svelte'
});

if (!manifest) throw new Error('Manifest generation failed');

let counter = 0;

export const server = new Elysia()
	.use(staticPlugin({ assets: './example/build', prefix: '' }))

	// HTML
	.get('/', () =>
		handleHTMLPageRequest('./example/build/html/pages/HTMLExample.html')
	)

	// React
	.get('/react', () =>
		handleReactPageRequest(ReactExample, manifest['ReactExampleIndex'], {
			test: 123
		})
	)

	// Svelte
	.get('/svelte', () =>
		handleSveltePageRequest(SvelteExample, manifest, { test: 456 })
	)

	// HTMX demo
	.get('/htmx', () => file('./example/build/htmx/HtmxHome.html'))
	.get('/htmx/increment', () => new Response(String(++counter)))

	.use(networkingPlugin)
	.on('error', (error) => {
		const { request } = error;
		console.error(
			`Server error on ${request.method} ${request.url}: ${error.message}`
		);
	});
```

### How it works

1. **`build()`** scans your project, bundles each framework, and returns a **manifest** that has the server, and client assets required to serve each route.
2. Route handlers (`handleReactPageRequest`, `handleSveltePageRequest`, …) stream HTML and inject scripts/assets based on that manifest.
3. The static plugin serves all compiled files from `/build`.

---

## Plugin System

Absolute JS piggybacks on the [Elysia plugin API](https://elysiajs.com/plugins). Any Elysia plugin works out of the box; Absolute adds helpers for:

| Plugin                 | Description                                                                                       |
| ---------------------- | ------------------------------------------------------------------------------------------------- |
| **`absolute-auth`**    | Full OAuth2 flow configured with 66 providers and allows full customizability with event handlers |
| **`networkingPlugin`** | Starts your Elysia server with HOST/PORT defaults from environment variables                      |

### Elysia composition contract

This contract is written for application authors and coding agents. It avoids
the runaway TypeScript instantiation cost that can occur when one inferred
Elysia application is repeatedly extended and re-aliased.

- Start every independently owned route surface from a named `new Elysia(...)`.
- Give each surface its shared context and plugins explicitly. Do not create
  `adminApp` by extending `publicApp`, for example.
- Prefer one shallow `.use([auth, metrics])` over a long sequence of `.use()`
  calls. `absolute/elysia-composition-boundaries` enforces this and safely
  auto-fixes comment-free chains.
- Mount independent route surfaces at the platform root. Export each real
  sub-application type for Eden consumers instead of exporting an accumulated
  server alias.
- Keep `elysia` and `@sinclair/typebox` on one physical installed identity
  across the workspace. Run `absolute doctor`; `absolute doctor --fix` aligns
  root overrides and rebuilds Bun's dependency graph when peer contexts drift.

After a dependency change, measure a cold typecheck once. Warm incremental
checks can hide an unhealthy graph:

```bash
/usr/bin/time -v bun run tsc --noEmit --incremental false
```

---

## Configuration Philosophy

Everything funnels through a single `build()` call:

```ts
await build({
	reactDirectory: 'src/react',
	svelteDirectory: 'src/svelte',
	htmlDirectory: 'src/html',
	htmxDirectory: 'src/htmx',
	assetsDirectory: 'public/assets'
});
```

No separate config files or environment variables—just explicit arguments with sensible defaults.

## Workspace Dev Logs

`absolute workspace dev` keeps the TUI focused on service status and live service output. Full logs are also written to `.absolutejs/workspace/logs/`, including `all.log` and one file per service, so long output can be copied or searched outside the TUI:

```bash
tail -n 200 .absolutejs/workspace/logs/all.log
```

---

## Roadmap

- **Angular** handlers
- Prisma support
- Biome support
- Hot‑reload development server
- First‑class Docker images & hosting recipes

---

## Contributing

Pull requests and issues are welcome! Whether it’s a new plugin, framework handler, or docs improvement:

1. Fork & branch.
2. `bun install && bun test`.
3. Submit a PR with a clear description.

---

## License

**Business Source License 1.1 (BSL-1.1)** – see [`LICENSE`](./LICENSE) for details.
