From 76b5cb51421ae77d239629f3c9ccee23383774e8 Mon Sep 17 00:00:00 2001 From: Juergen Kunz Date: Fri, 5 Dec 2025 10:00:40 +0000 Subject: [PATCH] fix(readme): Update README to reflect new features and updated examples (SPA/PWA/Edge/ServiceWorker) and clarify API usage --- changelog.md | 9 ++ readme.md | 195 ++++++++++++++++++--------------------- ts/00_commitinfo_data.ts | 2 +- 3 files changed, 102 insertions(+), 104 deletions(-) diff --git a/changelog.md b/changelog.md index aecaa64..cb040d5 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,14 @@ # Changelog +## 2025-12-05 - 7.8.18 - fix(readme) +Update README to reflect new features and updated examples (SPA/PWA/Edge/ServiceWorker) and clarify API usage + +- Rewrite project introduction and features list to highlight Service Worker, Edge Workers, SPA support, and PWA readiness +- Replace and expand example sections: Basic Server, Full Configuration, TypedRequest handlers, WebSocket usage, Edge Worker entrypoint, and Service Worker client usage +- Update configuration reference: remove legacy compression flags, add spaFallback, defaultAnswer, feedMetadata, and blockWaybackMachine options +- Document package exports and add examples for utility servers (WebsiteServer, ServiceServer) +- Clarify TypedRequest/TypedSocket usage by showing server.typedrouter and service worker client initializer (getServiceworkerClient) + ## 2025-12-04 - 7.8.11 - fix(web_inject) Improve logging in web injection (TypedRequest) and update dees-comms dependency diff --git a/readme.md b/readme.md index 0812c10..54c3861 100644 --- a/readme.md +++ b/readme.md @@ -1,6 +1,6 @@ # @api.global/typedserver -A powerful TypeScript-first web server framework featuring static file serving, live reload, compression, and seamless type-safe API integration. Part of the `@api.global` ecosystem, it provides a modern foundation for building full-stack TypeScript applications with first-class support for typed HTTP requests and WebSocket communication. +A TypeScript-first web server framework for building modern full-stack applications. Features static file serving, live reload, type-safe API integration, service worker support, and edge computing capabilities. Part of the `@api.global` ecosystem. ## Issue Reporting and Security @@ -8,15 +8,14 @@ For reporting bugs, issues, or security vulnerabilities, please visit [community ## ✨ Features -- πŸ”’ **Type-Safe API Ecosystem** - Full TypeScript support with `@api.global/typedrequest` and `@api.global/typedsocket` +- πŸ”’ **Type-Safe API** - Full TypeScript support with `@api.global/typedrequest` and `@api.global/typedsocket` - ⚑ **Live Reload** - Automatic browser refresh on file changes during development -- πŸ—œοΈ **Compression** - Built-in support for gzip, deflate, and brotli compression -- 🌐 **CORS Management** - Flexible cross-origin resource sharing configuration -- πŸ”§ **Service Worker Integration** - Advanced caching and offline capabilities -- ☁️ **Edge Worker Support** - Cloudflare Workers compatible edge computing -- πŸ“‘ **WebSocket Support** - Real-time bidirectional communication via TypedSocket -- πŸ—ΊοΈ **Sitemap & Feeds** - Automatic sitemap and RSS feed generation -- πŸ€– **Robots.txt** - Built-in robots.txt handling +- πŸ› οΈ **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 ## πŸ“¦ Installation @@ -30,7 +29,7 @@ npm install @api.global/typedserver ## πŸš€ Quick Start -### Basic Static File Server +### Basic Server ```typescript import { TypedServer } from '@api.global/typedserver'; @@ -43,10 +42,10 @@ const server = new TypedServer({ }); await server.start(); -console.log('Server running on port 3000'); +console.log('Server running!'); ``` -### Server with All Options +### Full Configuration ```typescript import { TypedServer } from '@api.global/typedserver'; @@ -55,15 +54,23 @@ const server = new TypedServer({ port: 8080, serveDir: './dist', cors: true, + + // Development watch: true, injectReload: true, - enableCompression: true, - preferredCompressionMethod: 'brotli', - forceSsl: false, + + // Production + forceSsl: true, + spaFallback: true, // Serve index.html for client-side routes + + // SEO sitemap: true, feed: true, robots: true, domain: 'example.com', + blockWaybackMachine: false, + + // PWA appVersion: 'v1.0.0', manifest: { name: 'My App', @@ -83,11 +90,11 @@ await server.start(); ### Adding TypedRequest Handlers ```typescript -import { TypedServer, servertools } from '@api.global/typedserver'; +import { TypedServer } from '@api.global/typedserver'; import * as typedrequest from '@api.global/typedrequest'; // Define your typed request interface -interface IGetUser { +interface IGetUser extends typedrequest.implementsTR { method: 'getUser'; request: { userId: string }; response: { name: string; email: string }; @@ -95,94 +102,46 @@ interface IGetUser { const server = new TypedServer({ serveDir: './public', cors: true }); -// Create a typed router -const typedRouter = new typedrequest.TypedRouter(); - -// Add a typed handler -typedRouter.addTypedHandler( +// Add a typed handler directly to the server's router +server.typedrouter.addTypedHandler( new typedrequest.TypedHandler('getUser', async (data) => { - // Your logic here return { name: 'John Doe', email: 'john@example.com' }; }) ); -// Attach the router to the server -server.server.addRoute('/api', new servertools.HandlerTypedRouter(typedRouter)); - await server.start(); ``` -### WebSocket Communication with TypedSocket +### Real-Time WebSocket Communication + +TypedServer automatically sets up TypedSocket for real-time communication: ```typescript import { TypedServer } from '@api.global/typedserver'; import * as typedrequest from '@api.global/typedrequest'; -import * as typedsocket from '@api.global/typedsocket'; -const server = new TypedServer({ serveDir: './public', cors: true }); -const typedRouter = new typedrequest.TypedRouter(); - -await server.start(); - -// Create WebSocket server attached to the HTTP server -const socketServer = await typedsocket.TypedSocket.createServer( - typedRouter, - server.server -); - -// Handle real-time events -interface IChatMessage { +interface IChatMessage extends typedrequest.implementsTR { method: 'sendMessage'; request: { text: string; room: string }; response: { messageId: string; timestamp: number }; } -typedRouter.addTypedHandler( +const server = new TypedServer({ serveDir: './public', cors: true }); + +// Handle real-time messages +server.typedrouter.addTypedHandler( new typedrequest.TypedHandler('sendMessage', async (data) => { return { messageId: crypto.randomUUID(), timestamp: Date.now() }; }) ); -``` -## πŸ› οΈ Server Tools +await server.start(); -### Custom Route Handlers - -```typescript -import { servertools } from '@api.global/typedserver'; - -const server = new servertools.Server({ - cors: true, - domain: 'example.com', -}); - -// Add a custom route with handler -server.addRoute('/api/hello', new servertools.Handler('GET', async (req, res) => { - res.json({ message: 'Hello, World!' }); -})); - -// Serve static files from a directory -server.addRoute('/{*splat}', new servertools.HandlerStatic('./public', { - serveIndexHtmlDefault: true, - enableCompression: true, -})); - -await server.start(3000); -``` - -### Proxy Handler - -```typescript -import { servertools } from '@api.global/typedserver'; - -const server = new servertools.Server({ cors: true }); - -// Proxy requests to another server -server.addRoute('/proxy/{*splat}', new servertools.HandlerProxy({ - target: 'https://api.example.com', -})); - -await server.start(3000); +// Push messages to connected clients +const connections = await server.typedsocket.findAllTargetConnectionsByTag('typedserver_frontend'); +for (const conn of connections) { + // Push to specific clients +} ``` ## ☁️ Edge Worker (Cloudflare Workers) @@ -190,36 +149,44 @@ await server.start(3000); ```typescript import { EdgeWorker, DomainRouter } from '@api.global/typedserver/edgeworker'; -const router = new DomainRouter(); +const worker = new EdgeWorker(); -router.addDomainInstruction({ +// Configure domain routing +worker.domainRouter.addDomainInstruction({ domainPattern: '*.example.com', originUrl: 'https://origin.example.com', + type: 'cache', cacheConfig: { maxAge: 3600 }, }); -const worker = new EdgeWorker(router); +worker.domainRouter.addDomainInstruction({ + domainPattern: 'api.example.com', + originUrl: 'https://api-origin.example.com', + type: 'origin', // Pass through to origin +}); -// In your Cloudflare Worker entry point +// Cloudflare Worker entry point export default { - fetch: (request: Request, env: any, ctx: any) => worker.handleRequest(request, env, ctx), + fetch: worker.fetchFunction.bind(worker), }; ``` ## πŸ”§ Service Worker Client +Manage service workers in your frontend application: + ```typescript -import { ServiceWorkerClient } from '@api.global/typedserver/web_serviceworker_client'; +import { getServiceworkerClient } from '@api.global/typedserver/web_serviceworker_client'; -const swClient = new ServiceWorkerClient(); - -// Register and manage service worker -await swClient.register('/serviceworker.bundle.js'); - -// Listen for updates -swClient.onUpdate(() => { - console.log('New version available!'); +// Initialize and register service worker +const swClient = await getServiceworkerClient({ + pollInterval: 30000, // Poll for updates every 30s }); + +// The service worker handles: +// - Cache invalidation from server +// - Offline support +// - Background sync ``` ## πŸ“‹ Configuration Reference @@ -233,9 +200,8 @@ swClient.onUpdate(() => { | `cors` | `boolean` | `true` | Enable CORS headers | | `watch` | `boolean` | `false` | Watch files for changes | | `injectReload` | `boolean` | `false` | Inject live reload script into HTML | -| `enableCompression` | `boolean` | `false` | Enable response compression | -| `preferredCompressionMethod` | `'gzip' \| 'deflate' \| 'brotli'` | - | Preferred compression algorithm | | `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 | @@ -244,16 +210,39 @@ swClient.onUpdate(() => { | `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 | -## πŸ—οΈ Architecture +## πŸ—οΈ Package Exports ``` @api.global/typedserver -β”œβ”€β”€ /backend - Main server exports (TypedServer, servertools) -β”œβ”€β”€ /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 +β”œβ”€β”€ /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 + +Pre-configured server templates for common use cases: + +```typescript +import { utilityservers } from '@api.global/typedserver'; + +// WebsiteServer - optimized for static websites +const websiteServer = new utilityservers.WebsiteServer({ + serveDir: './dist', + domain: 'example.com', +}); + +// ServiceServer - optimized for API services +const serviceServer = new utilityservers.ServiceServer({ + cors: true, +}); ``` ## License and Legal Information diff --git a/ts/00_commitinfo_data.ts b/ts/00_commitinfo_data.ts index c4c4cf8..fc6bb76 100644 --- a/ts/00_commitinfo_data.ts +++ b/ts/00_commitinfo_data.ts @@ -3,6 +3,6 @@ */ export const commitinfo = { name: '@api.global/typedserver', - version: '7.8.11', + version: '7.8.18', description: 'A TypeScript-based project for easy serving of static files with support for live reloading, compression, and typed requests.' }