CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-astrojs--node

Node.js adapter for Astro framework enabling server-side rendering and standalone server deployments

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

server-management.mddocs/

Server Management

Server creation and management utilities for HTTP/HTTPS servers with graceful shutdown, networking features, and logging capabilities.

Capabilities

Create Server

Creates HTTP or HTTPS server with SSL support, graceful shutdown capabilities, and network interface detection.

/**
 * Creates HTTP/HTTPS server with SSL support via environment variables
 * Includes graceful shutdown and server-destroy integration
 * @param listener - Request listener function for handling requests
 * @param host - Host to bind server to
 * @param port - Port to bind server to
 * @returns PreviewServer instance with control methods and server access
 */
function createServer(
  listener: http.RequestListener, 
  host: string, 
  port: number
): PreviewServer & { server: http.Server | https.Server };

interface PreviewServer {
  /** Host server is bound to */
  host: string;
  /** Port server is listening on */
  port: number;
  /** Promise that resolves when server is closed */
  closed(): Promise<void>;
  /** Gracefully stop the server */
  stop(): Promise<void>;
}

Usage Examples:

import { createServer } from "@astrojs/node/standalone.js";
import { createStandaloneHandler } from "@astrojs/node/standalone.js";

const handler = createStandaloneHandler(app, options);
const { server, host, port, stop } = createServer(handler, "localhost", 8080);

// Server is ready to accept connections
console.log(`Server created on ${host}:${port}`);

// Graceful shutdown
process.on('SIGTERM', async () => {
  await stop();
  process.exit(0);
});

HTTPS Configuration:

# Environment variables for SSL
export SERVER_CERT_PATH="/path/to/certificate.pem"
export SERVER_KEY_PATH="/path/to/private-key.pem"

Standalone Server

Creates and starts a complete standalone server with automatic configuration and logging.

/**
 * Creates and starts standalone HTTP/HTTPS server
 * Automatically resolves host/port from environment and options
 * @param app - NodeApp instance for request handling
 * @param options - Resolved adapter options including host/port configuration
 * @returns Server instance with done promise for shutdown handling
 */
function standalone(
  app: NodeApp, 
  options: Options
): { 
  server: PreviewServer & { server: http.Server | https.Server }; 
  done: Promise<void>; 
};

Usage Examples:

import { NodeApp } from "astro/app/node";
import standalone from "@astrojs/node/standalone.js";

const app = new NodeApp(manifest);
const { server, done } = standalone(app, options);

// Wait for server to close
await done;

Environment Variable Resolution:

  • PORT: Overrides options.port (default: 8080)
  • HOST: Overrides resolved host from options.host
  • ASTRO_NODE_LOGGING: Set to 'disabled' to suppress startup logging

Host Options Resolution

Resolves host configuration for server binding with sensible defaults.

/**
 * Resolves host value for server binding
 * @param host - Host configuration from options (boolean or string)
 * @returns Resolved host string for server.listen()
 */
function hostOptions(host: Options['host']): string;

/**
 * Resolves host configuration for HTTP server binding used in logging and preview
 * @param host - Host configuration from options or CLI arguments  
 * @returns Resolved host string for server operations
 */
function getResolvedHostForHttpServer(host: string | boolean | undefined): string | undefined;

Host Resolution Logic:

  • true: Returns '0.0.0.0' (listen on all interfaces)
  • false: Returns 'localhost' (secure default)
  • string: Returns the provided host value
  • IPv6 addresses are properly formatted with brackets

Usage Examples:

import { hostOptions } from "@astrojs/node/standalone.js";

// Configuration examples
console.log(hostOptions(true));        // '0.0.0.0'
console.log(hostOptions(false));       // 'localhost'  
console.log(hostOptions('127.0.0.1')); // '127.0.0.1'
console.log(hostOptions('::1'));       // '::1'

SSL/TLS Support

Certificate Configuration

Automatic HTTPS server creation when certificate files are provided:

if (process.env.SERVER_CERT_PATH && process.env.SERVER_KEY_PATH) {
  httpServer = https.createServer(
    {
      key: fs.readFileSync(process.env.SERVER_KEY_PATH),
      cert: fs.readFileSync(process.env.SERVER_CERT_PATH),
    },
    listener,
  );
} else {
  httpServer = http.createServer(listener);
}

Certificate Requirements:

  • Both SERVER_CERT_PATH and SERVER_KEY_PATH must be set
  • Files must be readable by the Node.js process
  • Standard PEM format certificates are expected
  • Self-signed certificates are supported for development

Certificate Formats:

  • Certificate: PEM-encoded certificate file (.pem, .crt)
  • Private Key: PEM-encoded private key file (.key, .pem)
  • Chain Certificates: Include intermediate certificates in cert file

HTTPS Examples

# Development with self-signed certificates
export SERVER_CERT_PATH="./certs/dev-cert.pem"
export SERVER_KEY_PATH="./certs/dev-key.pem"
npm run preview

# Production with CA-signed certificates
export SERVER_CERT_PATH="/etc/ssl/certs/domain.pem"
export SERVER_KEY_PATH="/etc/ssl/private/domain.key"
node dist/server.js

Graceful Shutdown

Server Destroy Integration

Uses server-destroy library for graceful connection termination:

import enableDestroy from 'server-destroy';

const httpServer = http.createServer(listener);
enableDestroy(httpServer);

// Graceful shutdown capability
async stop() {
  await new Promise((resolve, reject) => {
    httpServer.destroy((err) => (err ? reject(err) : resolve(undefined)));
  });
}

Shutdown Process:

  1. Stop accepting new connections
  2. Close existing idle connections
  3. Wait for active connections to complete
  4. Force-close remaining connections after timeout

Promise-Based Lifecycle

// Resolves when server is closed
const closed = new Promise<void>((resolve, reject) => {
  httpServer.addListener('close', resolve);
  httpServer.addListener('error', reject);
});

Lifecycle Events:

  • 'listening': Server is ready to accept connections
  • 'close': Server has stopped accepting connections
  • 'error': Server encountered an error during operation

Network Logging

Address Detection

Comprehensive network address detection and logging with local and network interface discovery:

/**
 * Logs server listening information with network address detection
 * @param logger - Astro integration logger for formatted output
 * @param server - HTTP/HTTPS server instance
 * @param configuredHost - Host configuration for address resolution
 * @returns Promise that resolves when logging is complete
 */
function logListeningOn(
  logger: AstroIntegrationLogger,
  server: http.Server | https.Server,
  configuredHost: string | boolean | undefined
): Promise<void>;

Network Interface Detection:

  • Scans all network interfaces using os.networkInterfaces()
  • Filters for IPv4 addresses (supports Node.js 18.0-18.3 compatibility)
  • Separates local (127.0.0.1) and network addresses
  • Handles IPv6 addresses with proper bracket formatting

Example Logging Output:

# Wildcard host (0.0.0.0 or ::)
Server listening on 
  local: http://localhost:8080 	
  network: http://192.168.1.100:8080

# Specific host
Server listening on http://localhost:8080

Wildcard Host Detection

const wildcardHosts = new Set(['0.0.0.0', '::', '0000:0000:0000:0000:0000:0000:0000:0000']);

if (host === undefined || wildcardHosts.has(host)) {
  // Show both local and network addresses
} else {
  // Show only the configured address
}

Error Handling

Server Creation Errors

Common server creation and startup errors:

// Port already in use
server.on('error', (err) => {
  if (err.code === 'EADDRINUSE') {
    console.error(`Port ${port} is already in use`);
  }
});

// Permission denied (privileged ports)
if (err.code === 'EACCES') {
  console.error(`Permission denied binding to port ${port}`);
}

SSL Configuration Errors

HTTPS-specific error handling:

try {
  const cert = fs.readFileSync(process.env.SERVER_CERT_PATH);
  const key = fs.readFileSync(process.env.SERVER_KEY_PATH);
} catch (err) {
  console.error('Failed to read SSL certificate files:', err.message);
  process.exit(1);
}

Common SSL Errors:

  • ENOENT: Certificate or key file not found
  • EACCES: Permission denied reading certificate files
  • Invalid Certificate: Malformed PEM data
  • Key Mismatch: Certificate and private key don't match

Shutdown Errors

Graceful shutdown error handling:

async stop() {
  try {
    await new Promise((resolve, reject) => {
      httpServer.destroy((err) => (err ? reject(err) : resolve(undefined)));
    });
  } catch (err) {
    console.error('Error during server shutdown:', err);
    throw err;
  }
}

Production Deployment Patterns

Process Management

// Graceful shutdown handling
process.on('SIGTERM', async () => {
  console.log('Received SIGTERM, shutting down gracefully');
  await server.stop();
  process.exit(0);
});

process.on('SIGINT', async () => {
  console.log('Received SIGINT, shutting down gracefully');
  await server.stop();
  process.exit(0);
});

Health Checks

import { createStandaloneHandler } from "@astrojs/node/standalone.js";

const handler = createStandaloneHandler(app, options);

// Wrap handler with health check
const healthCheckHandler = (req, res) => {
  if (req.url === '/health') {
    res.writeHead(200, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify({ status: 'ok', timestamp: Date.now() }));
    return;
  }
  
  return handler(req, res);
};

const server = createServer(healthCheckHandler, host, port);

Load Balancer Integration

// Trust proxy headers for load balancer setups
const handler = (req, res) => {
  // Handle X-Forwarded-For, X-Forwarded-Proto headers
  req.headers['x-forwarded-host'] = req.headers['x-forwarded-host'] || req.headers.host;
  
  return standaloneHandler(req, res);
};

docs

handlers.md

index.md

integration.md

preview.md

server-management.md

server-runtime.md

tile.json