fix(build): migrate build tooling to tsbuild v4 and tsbundle config while updating sitemap integration
This commit is contained in:
160
readme.md
160
readme.md
@@ -8,16 +8,18 @@ For reporting bugs, issues, or security vulnerabilities, please visit [community
|
||||
|
||||
## ✨ Features
|
||||
|
||||
- 🔒 **Type-Safe API** - Full TypeScript support with `@api.global/typedrequest` and `@api.global/typedsocket`
|
||||
- 🎯 **Decorator Routing** - Clean, expressive routing with `@Route`, `@Get`, `@Post` decorators via smartserve
|
||||
- 🛡️ **Security Headers** - Built-in CSP, HSTS, X-Frame-Options, and comprehensive security configuration
|
||||
- ⚡ **Live Reload** - Automatic browser refresh on file changes during development
|
||||
- 🛠️ **Service Worker** - Advanced caching, offline support, and background sync
|
||||
- ☁️ **Edge Workers** - Cloudflare Workers compatible edge computing with domain routing
|
||||
- 📡 **WebSocket** - Real-time bidirectional communication via TypedSocket
|
||||
- 🗺️ **SEO Tools** - Built-in sitemap, RSS feed, and robots.txt generation
|
||||
- 🎯 **SPA Support** - Single-page application fallback routing
|
||||
- 📱 **PWA Ready** - Web App Manifest generation for progressive web apps
|
||||
- 🔒 **Type-Safe API** — Full TypeScript support with `@api.global/typedrequest` and `@api.global/typedsocket`
|
||||
- 🎯 **Decorator Routing** — Clean, expressive routing with `@Route`, `@Get`, `@Post` decorators via smartserve
|
||||
- 🛡️ **Security Headers** — Built-in CSP, HSTS, X-Frame-Options, and comprehensive security configuration
|
||||
- ⚡ **Live Reload** — Automatic browser refresh on file changes during development
|
||||
- 🛠️ **Service Worker** — Advanced caching, offline support, and background sync
|
||||
- ☁️ **Edge Workers** — Cloudflare Workers compatible edge computing with domain routing
|
||||
- 📡 **WebSocket** — Real-time bidirectional communication via TypedSocket
|
||||
- 🗺️ **SEO Tools** — Built-in sitemap, RSS feed, and robots.txt generation
|
||||
- 🎯 **SPA Support** — Single-page application fallback routing
|
||||
- 📱 **PWA Ready** — Web App Manifest generation for progressive web apps
|
||||
- 🗜️ **Compression** — Automatic Brotli + Gzip response compression
|
||||
- 📦 **Bundled Content** — Serve pre-bundled content from memory for zero-filesystem deployments
|
||||
|
||||
## 📦 Installation
|
||||
|
||||
@@ -60,10 +62,11 @@ const server = new TypedServer({
|
||||
// Development
|
||||
watch: true,
|
||||
injectReload: true,
|
||||
noCache: true, // Disable browser caching
|
||||
|
||||
// Production
|
||||
forceSsl: true,
|
||||
spaFallback: true, // Serve index.html for client-side routes
|
||||
spaFallback: true, // Serve index.html for client-side routes
|
||||
|
||||
// SEO
|
||||
sitemap: true,
|
||||
@@ -82,6 +85,13 @@ const server = new TypedServer({
|
||||
background_color: '#ffffff',
|
||||
theme_color: '#000000',
|
||||
},
|
||||
|
||||
// Compression
|
||||
compression: {
|
||||
enabled: true,
|
||||
algorithms: ['br', 'gzip'],
|
||||
threshold: 1024,
|
||||
},
|
||||
});
|
||||
|
||||
await server.start();
|
||||
@@ -142,24 +152,23 @@ import { TypedServer } from '@api.global/typedserver';
|
||||
const server = new TypedServer({ serveDir: './public', cors: true });
|
||||
|
||||
// Simple route
|
||||
server.addRoute('/api/health', 'GET', async (request) => {
|
||||
server.addRoute('/api/health', 'GET', async (ctx) => {
|
||||
return new Response(JSON.stringify({ status: 'ok' }), {
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
});
|
||||
});
|
||||
|
||||
// Route with parameters (Express-style :param syntax)
|
||||
server.addRoute('/api/items/:id', 'GET', async (request) => {
|
||||
const itemId = (request as any).params.id;
|
||||
server.addRoute('/api/items/:id', 'GET', async (ctx) => {
|
||||
const itemId = ctx.params.id;
|
||||
return new Response(JSON.stringify({ id: itemId }), {
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
});
|
||||
});
|
||||
|
||||
// Wildcard routes
|
||||
server.addRoute('/files/*path', 'GET', async (request) => {
|
||||
const filePath = (request as any).params.path;
|
||||
// Handle file serving logic
|
||||
server.addRoute('/files/*path', 'GET', async (ctx) => {
|
||||
const filePath = ctx.params.path;
|
||||
return new Response(`Requested: ${filePath}`);
|
||||
});
|
||||
|
||||
@@ -274,6 +283,33 @@ const swClient = await getServiceworkerClient({
|
||||
// - Version updates
|
||||
```
|
||||
|
||||
## 📦 Bundled Content
|
||||
|
||||
Serve pre-bundled content directly from memory — useful for single-binary deployments or embedding assets in server-side code:
|
||||
|
||||
```typescript
|
||||
import { TypedServer } from '@api.global/typedserver';
|
||||
|
||||
const server = new TypedServer({
|
||||
cors: true,
|
||||
bundledContent: [
|
||||
{
|
||||
path: '/index.html',
|
||||
contentBase64: Buffer.from('<html><body>Hello!</body></html>').toString('base64'),
|
||||
},
|
||||
{
|
||||
path: '/app.js',
|
||||
contentBase64: Buffer.from('console.log("loaded")').toString('base64'),
|
||||
},
|
||||
],
|
||||
spaFallback: true,
|
||||
});
|
||||
|
||||
await server.start();
|
||||
```
|
||||
|
||||
Bundled content takes priority over filesystem serving and supports ETag-based conditional requests with immutable caching.
|
||||
|
||||
## 🛡️ Security Headers
|
||||
|
||||
Configure comprehensive security headers including CSP, HSTS, and more:
|
||||
@@ -345,7 +381,7 @@ await server.start();
|
||||
|
||||
TypedServer supports automatic response compression using Brotli and Gzip. Compression is powered by smartserve and enabled by default.
|
||||
|
||||
### Global Configuration
|
||||
### Configuration
|
||||
|
||||
```typescript
|
||||
import { TypedServer } from '@api.global/typedserver';
|
||||
@@ -358,47 +394,19 @@ const server = new TypedServer({
|
||||
compression: true,
|
||||
|
||||
// Or disable completely
|
||||
compression: false,
|
||||
// compression: false,
|
||||
|
||||
// Or configure in detail
|
||||
compression: {
|
||||
enabled: true,
|
||||
algorithms: ['br', 'gzip'], // Preferred order
|
||||
threshold: 1024, // Min size to compress (bytes)
|
||||
level: 4, // Compression level (1-11 for brotli, 1-9 for gzip)
|
||||
exclude: ['/api/stream/*'], // Skip these paths
|
||||
},
|
||||
// compression: {
|
||||
// enabled: true,
|
||||
// algorithms: ['br', 'gzip'], // Preferred order
|
||||
// threshold: 1024, // Min size to compress (bytes)
|
||||
// level: 4, // Compression level (1-11 for brotli, 1-9 for gzip)
|
||||
// exclude: ['/api/stream/*'], // Skip these paths
|
||||
// },
|
||||
});
|
||||
```
|
||||
|
||||
### Per-Route Control with Decorators
|
||||
|
||||
Use `@Compress` and `@NoCompress` decorators for fine-grained control:
|
||||
|
||||
```typescript
|
||||
import * as smartserve from '@push.rocks/smartserve';
|
||||
|
||||
@smartserve.Route('/api')
|
||||
class ApiController {
|
||||
// Force maximum compression for this endpoint
|
||||
@smartserve.Get('/large-data')
|
||||
@smartserve.Compress({ level: 11 })
|
||||
async getLargeData(ctx: smartserve.IRequestContext): Promise<Response> {
|
||||
return new Response(JSON.stringify(largeDataset));
|
||||
}
|
||||
|
||||
// Disable compression for streaming endpoint
|
||||
@smartserve.Get('/events')
|
||||
@smartserve.NoCompress()
|
||||
async streamEvents(ctx: smartserve.IRequestContext): Promise<Response> {
|
||||
// Server-Sent Events shouldn't be compressed
|
||||
return new Response(eventStream, {
|
||||
headers: { 'Content-Type': 'text/event-stream' },
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Compression Options Reference
|
||||
|
||||
| Option | Type | Default | Description |
|
||||
@@ -416,37 +424,40 @@ class ApiController {
|
||||
|
||||
| Option | Type | Default | Description |
|
||||
|--------|------|---------|-------------|
|
||||
| `serveDir` | `string` | - | Directory to serve static files from |
|
||||
| `serveDir` | `string` | — | Directory to serve static files from |
|
||||
| `bundledContent` | `IBundledContentItem[]` | — | Base64-encoded files to serve from memory |
|
||||
| `port` | `number \| string` | `3000` | Port to listen on |
|
||||
| `cors` | `boolean` | `true` | Enable CORS headers |
|
||||
| `watch` | `boolean` | `false` | Watch files for changes |
|
||||
| `injectReload` | `boolean` | `false` | Inject live reload script into HTML |
|
||||
| `noCache` | `boolean` | `false` | Disable browser caching via response headers |
|
||||
| `forceSsl` | `boolean` | `false` | Redirect HTTP to HTTPS |
|
||||
| `spaFallback` | `boolean` | `false` | Serve index.html for non-file routes |
|
||||
| `sitemap` | `boolean` | `false` | Generate sitemap at `/sitemap` |
|
||||
| `feed` | `boolean` | `false` | Generate RSS feed at `/feed` |
|
||||
| `robots` | `boolean` | `false` | Serve robots.txt |
|
||||
| `domain` | `string` | - | Domain name for sitemap/feeds |
|
||||
| `appVersion` | `string` | - | Application version string |
|
||||
| `manifest` | `object` | - | Web App Manifest configuration |
|
||||
| `publicKey` | `string` | - | SSL certificate |
|
||||
| `privateKey` | `string` | - | SSL private key |
|
||||
| `defaultAnswer` | `function` | - | Custom default response handler |
|
||||
| `feedMetadata` | `object` | - | RSS feed metadata options |
|
||||
| `domain` | `string` | — | Domain name for sitemap/feeds |
|
||||
| `appVersion` | `string` | — | Application version string |
|
||||
| `manifest` | `object` | — | Web App Manifest configuration |
|
||||
| `publicKey` | `string` | — | SSL certificate |
|
||||
| `privateKey` | `string` | — | SSL private key |
|
||||
| `defaultAnswer` | `function` | — | Custom default response handler |
|
||||
| `feedMetadata` | `object` | — | RSS feed metadata options |
|
||||
| `blockWaybackMachine` | `boolean` | `false` | Block Wayback Machine archiving |
|
||||
| `securityHeaders` | `ISecurityHeaders` | - | Security headers configuration |
|
||||
| `securityHeaders` | `ISecurityHeaders` | — | Security headers configuration |
|
||||
| `compression` | `ICompressionConfig \| boolean` | `true` | Response compression configuration |
|
||||
|
||||
## 🏗️ Package Exports
|
||||
|
||||
```
|
||||
@api.global/typedserver
|
||||
├── . - Main server (TypedServer)
|
||||
├── /backend - Alias for main server
|
||||
├── /edgeworker - Cloudflare Workers edge computing
|
||||
├── /web_inject - Live reload script injection
|
||||
├── /web_serviceworker - Service Worker implementation
|
||||
└── /web_serviceworker_client - Service Worker client utilities
|
||||
├── . — Main server (TypedServer)
|
||||
├── /backend — Alias for main server
|
||||
├── /infohtml — Info HTML page generator
|
||||
├── /edgeworker — Cloudflare Workers edge computing
|
||||
├── /web_inject — Live reload script injection
|
||||
├── /web_serviceworker — Service Worker implementation
|
||||
└── /web_serviceworker_client — Service Worker client utilities
|
||||
```
|
||||
|
||||
## 🔄 Utility Servers
|
||||
@@ -455,7 +466,7 @@ Pre-configured server templates with best practices built-in.
|
||||
|
||||
### UtilityWebsiteServer
|
||||
|
||||
Optimized for modern web applications with SPA support enabled by default:
|
||||
Optimized for modern web applications with SPA support, live reload, and caching disabled by default during development:
|
||||
|
||||
```typescript
|
||||
import { utilityservers } from '@api.global/typedserver';
|
||||
@@ -479,7 +490,7 @@ const websiteServer = new utilityservers.UtilityWebsiteServer({
|
||||
},
|
||||
|
||||
// Compression (enabled by default)
|
||||
compression: true, // or { level: 6, threshold: 512 }
|
||||
compression: true,
|
||||
|
||||
// Other options
|
||||
cors: true, // default: true
|
||||
@@ -551,9 +562,10 @@ await serviceServer.start();
|
||||
│ ┌─────────────────────────────────────────────────────┐ │
|
||||
│ │ Request Handler Pipeline │ │
|
||||
│ │ 1. Controller Registry (Decorated Routes) │ │
|
||||
│ │ 2. TypedRequest/TypedSocket handlers │ │
|
||||
│ │ 3. Static File Serving │ │
|
||||
│ │ 4. SPA Fallback │ │
|
||||
│ │ 2. Bundled Content (in-memory) │ │
|
||||
│ │ 3. HTML Injection (live reload) │ │
|
||||
│ │ 4. Static File Serving (filesystem) │ │
|
||||
│ │ 5. SPA Fallback │ │
|
||||
│ └─────────────────────────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user