BREAKING CHANGE(typedserver): Migrate to new push.rocks packages and async smartfs API; replace smartchok with smartwatch; update deps and service worker handling
This commit is contained in:
405
readme.md
405
readme.md
@@ -1,249 +1,278 @@
|
||||
# @api.global/typedserver
|
||||
|
||||
A TypeScript-based framework for serving static files with advanced features including live reloading, compression, and type-safe API requests. Part of the @api.global ecosystem, it integrates seamlessly with @api.global/typedrequest for type-safe HTTP requests and @api.global/typedsocket for WebSocket communication.
|
||||
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.
|
||||
|
||||
## Features
|
||||
## Issue Reporting and Security
|
||||
|
||||
- **Type-Safe API Ecosystem**:
|
||||
- HTTP Requests via @api.global/typedrequest
|
||||
- WebSocket Support via @api.global/typedsocket
|
||||
- Full TypeScript support across all endpoints
|
||||
- **Service Worker Integration**: Advanced caching and offline capabilities
|
||||
- **Edge Worker Support**: Optimized edge computing capabilities
|
||||
- **Live Reload**: Automatic browser refresh on file changes
|
||||
- **Compression**: Built-in support for response compression
|
||||
- **CORS Management**: Flexible cross-origin resource sharing
|
||||
- **TypeScript First**: Built with and for TypeScript
|
||||
For reporting bugs, issues, or security vulnerabilities, please visit [community.foss.global/](https://community.foss.global/). This is the central community hub for all issue reporting. Developers who sign and comply with our contribution agreement and go through identification can also get a [code.foss.global/](https://code.foss.global/) account to submit Pull Requests directly.
|
||||
|
||||
## Components
|
||||
## ✨ Features
|
||||
|
||||
### Core Server (`ts/`)
|
||||
- Static file serving with Express
|
||||
- Type-safe request handling
|
||||
- Live reload functionality
|
||||
- Compression middleware
|
||||
- 🔒 **Type-Safe API Ecosystem** - 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 (`ts_web_serviceworker/`)
|
||||
- `CacheManager`: Advanced caching strategies
|
||||
- `NetworkManager`: Request/response handling
|
||||
- `UpdateManager`: Cache invalidation and updates
|
||||
- `ServiceWorker`: Core service worker implementation
|
||||
|
||||
### Edge Worker (`ts_edgeworker/`)
|
||||
- Edge computing capabilities
|
||||
- Request/response transformation
|
||||
- Edge caching strategies
|
||||
|
||||
### Web Inject (`ts_web_inject/`)
|
||||
- Live reload script injection
|
||||
- Runtime dependency management
|
||||
- Dynamic module loading
|
||||
|
||||
## Installation
|
||||
## 📦 Installation
|
||||
|
||||
```bash
|
||||
# Using pnpm (recommended)
|
||||
pnpm add @api.global/typedserver
|
||||
|
||||
# Using npm
|
||||
npm install @api.global/typedserver
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
## 🚀 Quick Start
|
||||
|
||||
### Basic Static File Server
|
||||
|
||||
```typescript
|
||||
import { TypedServer } from '@api.global/typedserver';
|
||||
|
||||
const server = new TypedServer({
|
||||
port: 3000,
|
||||
serveDir: './public',
|
||||
watch: true,
|
||||
compression: true
|
||||
cors: true,
|
||||
watch: true, // Enable file watching
|
||||
injectReload: true, // Inject live reload script
|
||||
});
|
||||
|
||||
server.start();
|
||||
await server.start();
|
||||
console.log('Server running on port 3000');
|
||||
```
|
||||
|
||||
## Type-Safe API Integration
|
||||
### Server with All Options
|
||||
|
||||
### HTTP Requests with TypedRequest
|
||||
```typescript
|
||||
import { TypedRequest } from '@api.global/typedrequest';
|
||||
import { TypedServer } from '@api.global/typedserver';
|
||||
|
||||
// Define your request/response interface
|
||||
interface IUserRequest {
|
||||
const server = new TypedServer({
|
||||
port: 8080,
|
||||
serveDir: './dist',
|
||||
cors: true,
|
||||
watch: true,
|
||||
injectReload: true,
|
||||
enableCompression: true,
|
||||
preferredCompressionMethod: 'brotli',
|
||||
forceSsl: false,
|
||||
sitemap: true,
|
||||
feed: true,
|
||||
robots: true,
|
||||
domain: 'example.com',
|
||||
appVersion: 'v1.0.0',
|
||||
manifest: {
|
||||
name: 'My App',
|
||||
short_name: 'myapp',
|
||||
start_url: '/',
|
||||
display: 'standalone',
|
||||
background_color: '#ffffff',
|
||||
theme_color: '#000000',
|
||||
},
|
||||
});
|
||||
|
||||
await server.start();
|
||||
```
|
||||
|
||||
## 🔌 Type-Safe API Integration
|
||||
|
||||
### Adding TypedRequest Handlers
|
||||
|
||||
```typescript
|
||||
import { TypedServer, servertools } from '@api.global/typedserver';
|
||||
import * as typedrequest from '@api.global/typedrequest';
|
||||
|
||||
// Define your typed request interface
|
||||
interface IGetUser {
|
||||
method: 'getUser';
|
||||
request: { userId: string };
|
||||
response: { username: string; email: string; };
|
||||
response: { name: string; email: string };
|
||||
}
|
||||
|
||||
// Create and use a typed request
|
||||
const getUserRequest = new TypedRequest<IUserRequest>('/api/users', 'getUser');
|
||||
const user = await getUserRequest.fire({ userId: '123' });
|
||||
```
|
||||
const server = new TypedServer({ serveDir: './public', cors: true });
|
||||
|
||||
### WebSocket Communication
|
||||
```typescript
|
||||
import { TypedSocket } from '@api.global/typedsocket';
|
||||
// Create a typed router
|
||||
const typedRouter = new typedrequest.TypedRouter();
|
||||
|
||||
// Server setup
|
||||
const typedRouter = new TypedRouter();
|
||||
const server = await TypedSocket.createServer(typedRouter);
|
||||
|
||||
// Client connection
|
||||
const client = await TypedSocket.createClient(typedRouter, 'ws://localhost:3000');
|
||||
|
||||
// Type-safe real-time messaging
|
||||
interface IChatMessage {
|
||||
method: 'sendMessage';
|
||||
request: { text: string };
|
||||
response: { id: string; timestamp: number; };
|
||||
}
|
||||
```
|
||||
|
||||
## Advanced Usage
|
||||
|
||||
### Service Worker Setup
|
||||
|
||||
```typescript
|
||||
import { ServiceWorker } from '@api.global/typedserver/web_serviceworker';
|
||||
|
||||
const sw = new ServiceWorker({
|
||||
cacheStrategy: 'network-first',
|
||||
offlineSupport: true
|
||||
});
|
||||
|
||||
sw.register();
|
||||
```
|
||||
|
||||
### Edge Worker Configuration
|
||||
|
||||
```typescript
|
||||
import { EdgeWorker } from '@api.global/typedserver/edgeworker';
|
||||
|
||||
const edge = new EdgeWorker({
|
||||
transforms: ['compress', 'minify'],
|
||||
caching: true
|
||||
});
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
### Server Options
|
||||
```typescript
|
||||
interface IServerOptions {
|
||||
port?: number;
|
||||
host?: string;
|
||||
serveDir: string;
|
||||
watch?: boolean;
|
||||
compression?: boolean;
|
||||
cors?: boolean | CorsOptions;
|
||||
cache?: CacheOptions;
|
||||
}
|
||||
```
|
||||
|
||||
### Cache Strategies
|
||||
```typescript
|
||||
type CacheStrategy =
|
||||
| 'network-first'
|
||||
| 'cache-first'
|
||||
| 'stale-while-revalidate';
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
See [API Documentation](https://api.global/docs/typedserver) for detailed API reference.
|
||||
|
||||
## Contributing
|
||||
|
||||
1. Fork the repository
|
||||
2. Create your feature branch
|
||||
3. Commit your changes
|
||||
4. Push to the branch
|
||||
5. Create a Pull Request
|
||||
|
||||
## License
|
||||
|
||||
MIT License - see LICENSE for details.
|
||||
|
||||
Task Venture Capital GmbH © 2024
|
||||
|
||||
```typescript
|
||||
// Define a request type
|
||||
interface MyCustomRequest {
|
||||
userId: string;
|
||||
}
|
||||
|
||||
// Define a response type
|
||||
interface MyCustomResponse {
|
||||
userName: string;
|
||||
}
|
||||
```
|
||||
|
||||
Next, set up a route to handle requests using these types:
|
||||
|
||||
```typescript
|
||||
import { TypedRouter, TypedHandler } from '@api.global/typedrequest';
|
||||
|
||||
// Instantiate a TypedRouter
|
||||
const typedRouter = new TypedRouter();
|
||||
|
||||
// Register a route with request and response types
|
||||
typedRouter.addTypedHandler<MyCustomRequest, MyCustomResponse>(
|
||||
new TypedHandler('getUser', async (requestData) => {
|
||||
// Implement your logic here. For example, fetch user data from a database.
|
||||
const userData = { userName: 'John Doe' }; // Dummy implementation
|
||||
return { response: userData };
|
||||
// Add a typed handler
|
||||
typedRouter.addTypedHandler<IGetUser>(
|
||||
new typedrequest.TypedHandler('getUser', async (data) => {
|
||||
// Your logic here
|
||||
return { name: 'John Doe', email: 'john@example.com' };
|
||||
})
|
||||
);
|
||||
|
||||
// Bind the typed router to the server
|
||||
typedServer.useTypedRouter(typedRouter);
|
||||
// Attach the router to the server
|
||||
server.server.addRoute('/api', new servertools.HandlerTypedRouter(typedRouter));
|
||||
|
||||
// Now, the route is set up to handle requests with type checking
|
||||
await server.start();
|
||||
```
|
||||
|
||||
This example shows defining types for requests and responses, creating a `TypedRouter`, and adding a route with typed handling. This feature brings the benefits of TypeScript's static type checking to server-side logic, improving the development experience.
|
||||
|
||||
### Enabling SSL/TLS
|
||||
|
||||
To enable SSL/TLS, configure the `TypedServer` with the SSL options, including the paths to your SSL certificate and key files:
|
||||
### WebSocket Communication with TypedSocket
|
||||
|
||||
```typescript
|
||||
const serverOptions = {
|
||||
port: 443,
|
||||
serveDir: 'public',
|
||||
watch: true,
|
||||
injectReload: true,
|
||||
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 {
|
||||
method: 'sendMessage';
|
||||
request: { text: string; room: string };
|
||||
response: { messageId: string; timestamp: number };
|
||||
}
|
||||
|
||||
typedRouter.addTypedHandler<IChatMessage>(
|
||||
new typedrequest.TypedHandler('sendMessage', async (data) => {
|
||||
return { messageId: crypto.randomUUID(), timestamp: Date.now() };
|
||||
})
|
||||
);
|
||||
```
|
||||
|
||||
## 🛠️ Server Tools
|
||||
|
||||
### Custom Route Handlers
|
||||
|
||||
```typescript
|
||||
import { servertools } from '@api.global/typedserver';
|
||||
|
||||
const server = new servertools.Server({
|
||||
cors: true,
|
||||
privateKey: fs.readFileSync('path/to/ssl/private.key'),
|
||||
publicKey: fs.readFileSync('path/to/ssl/certificate.crt')
|
||||
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);
|
||||
```
|
||||
|
||||
## ☁️ Edge Worker (Cloudflare Workers)
|
||||
|
||||
```typescript
|
||||
import { EdgeWorker, DomainRouter } from '@api.global/typedserver/edgeworker';
|
||||
|
||||
const router = new DomainRouter();
|
||||
|
||||
router.addDomainInstruction({
|
||||
domainPattern: '*.example.com',
|
||||
originUrl: 'https://origin.example.com',
|
||||
cacheConfig: { maxAge: 3600 },
|
||||
});
|
||||
|
||||
const worker = new EdgeWorker(router);
|
||||
|
||||
// In your Cloudflare Worker entry point
|
||||
export default {
|
||||
fetch: (request: Request, env: any, ctx: any) => worker.handleRequest(request, env, ctx),
|
||||
};
|
||||
|
||||
const typedServer = new TypedServer(serverOptions);
|
||||
startServer().catch(console.error);
|
||||
```
|
||||
|
||||
Replace `'path/to/ssl/private.key'` and `'path/to/ssl/certificate.crt'` with the actual paths to your SSL key and certificate files. This setup ensures that your server communicates over HTTPS, encrypting the data transmitted between the client and the server.
|
||||
## 🔧 Service Worker Client
|
||||
|
||||
### Conclusion
|
||||
```typescript
|
||||
import { ServiceWorkerClient } from '@api.global/typedserver/web_serviceworker_client';
|
||||
|
||||
`@api.global/typedserver` offers a streamlined way to set up a web server with TypeScript, featuring static file serving, live reloading, typed request/response handling, and SSL support. This guide covers the basic usage, but `TypedServer` is highly configurable, catering to various hosting and development needs.
|
||||
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!');
|
||||
});
|
||||
```
|
||||
|
||||
For a deeper dive into the API and more advanced configurations, refer to the official documentation and type definitions included in the package.
|
||||
## 📋 Configuration Reference
|
||||
|
||||
### IServerOptions
|
||||
|
||||
| Option | Type | Default | Description |
|
||||
|--------|------|---------|-------------|
|
||||
| `serveDir` | `string` | - | Directory to serve static files from |
|
||||
| `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 |
|
||||
| `enableCompression` | `boolean` | `false` | Enable response compression |
|
||||
| `preferredCompressionMethod` | `'gzip' \| 'deflate' \| 'brotli'` | - | Preferred compression algorithm |
|
||||
| `forceSsl` | `boolean` | `false` | Redirect HTTP to HTTPS |
|
||||
| `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 |
|
||||
|
||||
## 🏗️ Architecture
|
||||
|
||||
```
|
||||
@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
|
||||
```
|
||||
|
||||
## License and Legal Information
|
||||
|
||||
This repository contains open-source code that is licensed under the MIT License. A copy of the MIT License can be found in the [license](license) file within this repository.
|
||||
This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the [LICENSE](./LICENSE) file.
|
||||
|
||||
**Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.
|
||||
|
||||
### Trademarks
|
||||
|
||||
This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH and are not included within the scope of the MIT license granted herein. Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines, and any usage must be approved in writing by Task Venture Capital GmbH.
|
||||
This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH or third parties, and are not included within the scope of the MIT license granted herein.
|
||||
|
||||
Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines or the guidelines of the respective third-party owners, and any usage must be approved in writing. Third-party trademarks used herein are the property of their respective owners and used only in a descriptive manner, e.g. for an implementation of an API or similar.
|
||||
|
||||
### Company Information
|
||||
|
||||
Task Venture Capital GmbH
|
||||
Registered at District court Bremen HRB 35230 HB, Germany
|
||||
Task Venture Capital GmbH
|
||||
Registered at District Court Bremen HRB 35230 HB, Germany
|
||||
|
||||
For any legal inquiries or if you require further information, please contact us via email at hello@task.vc.
|
||||
For any legal inquiries or further information, please contact us via email at hello@task.vc.
|
||||
|
||||
By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.
|
||||
|
||||
Reference in New Issue
Block a user