fix(build): migrate build tooling to tsbuild v4 and tsbundle config while updating sitemap integration

This commit is contained in:
2026-03-23 11:49:55 +00:00
parent d4c4e0971f
commit 292fb824fd
23 changed files with 3601 additions and 4401 deletions

160
readme.md
View File

@@ -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 │ │
│ └─────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
```