# SmartServe Development Hints

## Architecture Overview

SmartServe is a cross-platform HTTP server for Node.js, Deno, and Bun using:
- **Web Standards API** (Request/Response) for cross-platform compatibility
- **TC39 Stage 3 decorators** (TypeScript 5.0+) for route definition
- **Adapter pattern** for runtime-specific implementations

## Key Files

### Core
- `ts/core/smartserve.classes.smartserve.ts` - Main server class
- `ts/core/smartserve.interfaces.ts` - All type definitions
- `ts/core/smartserve.errors.ts` - HTTP error classes

### Adapters
- `ts/adapters/adapter.factory.ts` - Runtime detection via @push.rocks/smartenv
- `ts/adapters/adapter.node.ts` - Node.js with Request/Response conversion
- `ts/adapters/adapter.deno.ts` - Deno (zero overhead, native)
- `ts/adapters/adapter.bun.ts` - Bun (zero overhead, native)

### Decorators
- `ts/decorators/decorators.route.ts` - @Route class decorator
- `ts/decorators/decorators.methods.ts` - @Get, @Post, etc.
- `ts/decorators/decorators.interceptors.ts` - @Guard, @Transform, @Intercept
- `ts/decorators/decorators.registry.ts` - Controller registration and route matching

### Static Files
- `ts/files/file.server.ts` - Static file serving with streaming, ETags, directory listing
- `ts/utils/utils.mime.ts` - MIME type detection
- `ts/utils/utils.etag.ts` - ETag generation

### Compression
- `ts/compression/compression.runtime.ts` - Cross-runtime compression (Node.js zlib, Web CompressionStream)
- `ts/compression/compression.middleware.ts` - Compression config and helpers
- `ts/utils/utils.encoding.ts` - Accept-Encoding parsing
- `ts/decorators/decorators.compress.ts` - @Compress and @NoCompress decorators

### Protocols
- `ts/protocols/webdav/webdav.handler.ts` - WebDAV RFC 4918 handler
- `ts/protocols/webdav/webdav.xml.ts` - XML generation (multistatus, lock responses)
- `ts/protocols/webdav/webdav.types.ts` - WebDAV type definitions

## Decorator System

Uses TC39 decorators (NOT experimental decorators). Metadata stored via Symbol property on classes.

### Interceptor Execution Order (Onion Model)
```
Request → Class Guards → Method Guards → Handler → Method Transforms → Class Transforms → Response
```

### Guard vs Transform vs Intercept
- `@Guard(fn)` = `@Intercept({ request: fn })` - returns boolean (true=allow, false=403)
- `@Transform(fn)` = `@Intercept({ response: fn })` - modifies response
- `@Intercept({ request?, response? })` - full control

## Dependencies

Required:
- `@push.rocks/smartenv` - Runtime detection
- `@push.rocks/smartpath` - Path utilities
- `@push.rocks/smartlog` - Logging
- `@push.rocks/lik` - Collections

Optional:
- `ws` - WebSocket support for Node.js (Deno/Bun have native)

## WebDAV Usage

```typescript
import { SmartServe } from '@push.rocks/smartserve';

const server = new SmartServe({
  port: 8080,
  webdav: {
    root: '/path/to/files',
    auth: (ctx) => {
      // Optional auth - return true to allow, false to reject
      const auth = ctx.headers.get('Authorization');
      return auth === 'Basic dXNlcjpwYXNz';
    },
    locking: true, // Enable file locking (RFC 4918)
  }
});

await server.start();
// Mount at http://localhost:8080 as network drive
```

### Supported WebDAV Methods
- OPTIONS - Capability discovery
- PROPFIND - Directory listing and file metadata
- PROPPATCH - Property modification (returns 403)
- MKCOL - Create directory
- COPY - Copy files/directories
- MOVE - Move/rename files/directories
- LOCK/UNLOCK - Exclusive write locking
- GET/HEAD/PUT/DELETE - Standard file operations

## TypedRouter WebSocket Integration

SmartServe supports first-class TypedRouter integration for type-safe RPC over WebSockets.

### Usage

```typescript
import { SmartServe } from '@push.rocks/smartserve';
import { TypedRouter, TypedHandler } from '@api.global/typedrequest';

const router = new TypedRouter();
router.addTypedHandler(new TypedHandler('echo', async (data) => {
  return { echoed: data.message };
}));

const server = new SmartServe({
  port: 3000,
  websocket: {
    typedRouter: router,
    onConnectionOpen: (peer) => {
      peer.tags.add('authenticated');
      console.log(`Client connected: ${peer.id}`);
    },
    onConnectionClose: (peer) => {
      console.log(`Client disconnected: ${peer.id}`);
    },
  },
});

await server.start();

// Broadcast to all connections
server.broadcastWebSocket({ type: 'notification', message: 'Hello!' });

// Broadcast to specific tag
server.broadcastWebSocketByTag('authenticated', { type: 'secure-message' });

// Get all connections
const connections = server.getWebSocketConnections();
```

### Key Features

- **TypedRouter mode**: Set `typedRouter` for automatic JSON-RPC routing (mutually exclusive with `onMessage`)
- **Connection registry**: Active only when `typedRouter` is set
- **Peer tags**: Use `peer.tags.add/has/delete` for connection filtering
- **Broadcast methods**: `broadcastWebSocket()` and `broadcastWebSocketByTag()`
- **Lifecycle hooks**: `onConnectionOpen` and `onConnectionClose` (alongside existing `onOpen`/`onClose`)

### Architecture Notes

- `typedRouter` and `onMessage` are mutually exclusive (throws `WebSocketConfigError` if both set)
- Connection registry only active when `typedRouter` is configured
- Bun adapter stores peer ID/tags in `ws.data` for persistence across events
- Internal `_connectionCallbacks` passed to adapters for registry communication

## Compression

SmartServe supports automatic response compression with Brotli and gzip.

### Configuration

```typescript
const server = new SmartServe({
  port: 3000,

  // Simple: enable with defaults (compression is ON by default)
  compression: true,

  // Detailed configuration
  compression: {
    enabled: true,
    algorithms: ['br', 'gzip'],  // Brotli preferred, gzip fallback
    threshold: 1024,              // Don't compress < 1KB
    level: 4,                     // Compression level
    compressibleTypes: [          // Custom MIME types
      'text/',
      'application/json',
      'application/javascript',
    ],
    exclude: ['/api/stream/*'],   // Skip certain paths
  },

  // Pre-compressed static files
  static: {
    root: './public',
    precompressed: true,  // Serve index.html.br, index.html.gz if available
  },
});
```

### Per-Route Control

```typescript
@Controller('/api')
class ApiController {
  @Get('/data')
  getData() {
    return { large: 'json' };  // Compressed by default
  }

  @Get('/stream')
  @NoCompress()  // Skip compression for SSE/streaming
  getStream() {
    return new Response(eventStream, {
      headers: { 'Content-Type': 'text/event-stream' }
    });
  }

  @Get('/heavy')
  @Compress({ level: 11 })  // Force max brotli compression
  getHeavy() {
    return massiveData;
  }
}
```

### Cross-Runtime Support

| Runtime | Brotli | gzip | Implementation |
|---------|--------|------|----------------|
| Node.js | ✅ | ✅ | Native zlib module |
| Deno | ⚠️ | ✅ | CompressionStream API |
| Bun | ⚠️ | ✅ | CompressionStream API |

Note: Brotli in Deno/Bun falls back to gzip if CompressionStream doesn't support it.

## TODO

- [x] WebDAV protocol support (PROPFIND, MKCOL, COPY, MOVE, LOCK, UNLOCK)
- [x] TypedRouter WebSocket integration
- [x] Brotli/gzip compression with per-route control
- [ ] HTTP/2 support investigation
- [ ] Performance benchmarks
