platformservice/readme.hints.md

3.0 KiB

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
// 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:
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
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:
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)