2025-05-07 23:04:54 +00:00
|
|
|
# Implementation Hints and Learnings
|
|
|
|
|
|
|
|
## SmartProxy Usage
|
|
|
|
|
|
|
|
### Direct Component Usage
|
|
|
|
- Use SmartProxy components directly instead of creating your own wrappers
|
|
|
|
- SmartProxy already includes Port80Handler and NetworkProxy functionality
|
|
|
|
- When using SmartProxy, configure it directly rather than instantiating Port80Handler or NetworkProxy separately
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
// PREFERRED: Use SmartProxy with built-in ACME support
|
|
|
|
const smartProxy = new plugins.smartproxy.SmartProxy({
|
|
|
|
fromPort: 443,
|
|
|
|
toPort: targetPort,
|
|
|
|
targetIP: targetServer,
|
|
|
|
sniEnabled: true,
|
|
|
|
acme: {
|
|
|
|
port: 80,
|
|
|
|
enabled: true,
|
|
|
|
autoRenew: true,
|
|
|
|
useProduction: true,
|
|
|
|
renewThresholdDays: 30,
|
|
|
|
accountEmail: contactEmail
|
|
|
|
},
|
|
|
|
globalPortRanges: [{ from: 443, to: 443 }],
|
|
|
|
domainConfigs: [/* domain configurations */]
|
|
|
|
});
|
|
|
|
```
|
|
|
|
|
|
|
|
### Certificate Management
|
|
|
|
- SmartProxy has built-in ACME certificate management
|
|
|
|
- Configure it in the `acme` property of SmartProxy options
|
|
|
|
- Use `accountEmail` (not `email`) for the ACME contact email
|
|
|
|
- SmartProxy handles both HTTP-01 challenges and certificate application automatically
|
|
|
|
|
|
|
|
## qenv Usage
|
|
|
|
|
|
|
|
### Direct Usage
|
|
|
|
- Use qenv directly instead of creating environment variable wrappers
|
|
|
|
- Instantiate qenv with appropriate basePath and nogitPath:
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
const qenv = new plugins.qenv.Qenv('./', '.nogit/');
|
|
|
|
const value = await qenv.getEnvVarOnDemand('ENV_VAR_NAME');
|
|
|
|
```
|
|
|
|
|
|
|
|
## TypeScript Interfaces
|
|
|
|
|
|
|
|
### SmartProxy Interfaces
|
|
|
|
- Always check the interfaces from the node_modules to ensure correct property names
|
|
|
|
- Important interfaces:
|
|
|
|
- `ISmartProxyOptions`: Main configuration for SmartProxy
|
|
|
|
- `IAcmeOptions`: ACME certificate configuration
|
|
|
|
- `IDomainConfig`: Domain-specific configuration
|
|
|
|
|
|
|
|
### Required Properties
|
|
|
|
- Remember to include all required properties in your interface implementations
|
|
|
|
- For `ISmartProxyOptions`, `globalPortRanges` is required
|
|
|
|
- For `IAcmeOptions`, use `accountEmail` for the contact email
|
|
|
|
|
|
|
|
## Testing
|
|
|
|
|
|
|
|
### Test Structure
|
|
|
|
- Follow the project's test structure, using `@push.rocks/tapbundle`
|
|
|
|
- Use `expect(value).toEqual(expected)` for equality checks
|
|
|
|
- Use `expect(value).toBeTruthy()` for boolean assertions
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
tap.test('test description', async () => {
|
|
|
|
const result = someFunction();
|
|
|
|
expect(result.property).toEqual('expected value');
|
|
|
|
expect(result.valid).toBeTruthy();
|
|
|
|
});
|
|
|
|
```
|
|
|
|
|
|
|
|
### Cleanup
|
|
|
|
- Include a cleanup test to ensure proper test resource handling
|
|
|
|
- Add a `stop` test to forcefully end the test when needed:
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
tap.test('stop', async () => {
|
|
|
|
await tap.stopForcefully();
|
|
|
|
});
|
|
|
|
```
|
|
|
|
|
|
|
|
## Architecture Principles
|
|
|
|
|
|
|
|
### Simplicity
|
|
|
|
- Prefer direct usage of libraries instead of creating wrappers
|
|
|
|
- Don't reinvent functionality that already exists in dependencies
|
|
|
|
- Keep interfaces clean and focused, avoiding unnecessary abstraction layers
|
|
|
|
|
|
|
|
### Component Integration
|
|
|
|
- Leverage built-in integrations between components (like SmartProxy's ACME handling)
|
|
|
|
- Use parallel operations for performance (like in the `stop()` method)
|
|
|
|
- Separate concerns clearly (HTTP handling vs. SMTP handling)
|