Skip to content

Latest commit

 

History

History
129 lines (105 loc) · 6.84 KB

File metadata and controls

129 lines (105 loc) · 6.84 KB

WARP.md

This file provides guidance to WARP (warp.dev) when working with code in this repository.

Project overview

This is the Restspace Runtime, a Deno-based, multi-tenant HTTP runtime that loads “service components” and “adapters” via JSON manifests. The server lazily loads tenant configuration (services.json) from a configured store, routes requests by longest base-path match, wraps services with pre/post pipelines, applies CORS and caching, and supports internal request composition without network hops.

Common commands (pwsh-friendly)

  • Run (local rs-core via importMap.json)
deno run --allow-all --unstable --import-map=importMap.json server.ts ./serverConfig.json [port] [LOG_LEVEL]
# Examples:
# deno run --allow-all --unstable --import-map=importMap.json server.ts ./serverConfig.json 3100 INFO
# Debug inspector:
# deno run --inspect-brk --allow-all --unstable --import-map=importMap.json server.ts ./serverConfig.json 3100 DEBUG
  • Run using hosted core (no local ../rs-core checkout)
deno run --allow-all --unstable --import-map=importMapLib.json server.ts ./serverConfig.json 3100 INFO
  • Type-check, lint, format
# Type-check the entrypoint (uses import map via server.ts deps)
deno check --allow-import --unstable server.ts
# Lint all files
deno lint
# Format all files
deno fmt
# Refresh dependency cache
deno cache --import-map=importMap.json server.ts --reload
  • Tests
# Run all tests (uses test/ utilities and local file-backed test config)
deno test --unstable --allow-all test/
# Debug tests
deno test --inspect-brk --unstable --allow-all test/
# Run a single test file
deno test --unstable --allow-all test/pipeline.test.ts
# Filter by test name pattern
# (runs tests whose names match the regex)
deno test --unstable --allow-all --filter "pipeline"
# Optional: reset local test data (destructive)
# This clears C:\Dev\test\test-data used by tests
# Use with care and only if that path is safe to remove on your machine.
Remove-Item -Recurse -Force C:\Dev\test\test-data; New-Item -ItemType Directory C:\Dev\test\test-data | Out-Null
  • Bundle for production and run from bundle
# Produce bundled.js using esbuild with Deno loader (see bundle.ts)
deno run --allow-read --allow-write --allow-env --allow-run --allow-net --allow-import bundle.ts
# Optional Windows-specific post-step (fix-bundle)
./fix-bundle.ps1
# Run the bundle
deno run --allow-all --unsafely-ignore-certificate-errors=restspace.local bundled.js ./serverConfig.json 3100 INFO

Key configuration and environment

  • serverConfig.json controls tenancy, domains, infra, and storage backends.
    • tenancy: "single" | "multi"
    • mainDomain and domainMap: map hostnames to tenant names (used for routing)
    • infra: named adapter presets; configStore/stateStore select which infra to use
    • CORS setter is attached at runtime via getServerConfig.ts
  • Import maps:
    • importMap.json maps "rs-core/" to a local sibling checkout at ../rs-core
    • importMapLib.json maps "rs-core/" to the hosted library at https://lib.restspace.io/core/
  • Logging: configured in config.ts (RotatingFileHandler to ./main.log); pass LOG_LEVEL (e.g., DEBUG, INFO) as the 3rd CLI arg to server.ts

High-level architecture

  • Entry and serving

    • server.ts parses args: serverConfig path, port (default 3100), log level; initializes logging and starts Deno.serve
    • WebSocket upgrades are handled; otherwise request is converted to Message and dispatched
  • Request handling and routing

    • handleRequest.ts resolves tenant from Host header (tenantFromHostname)
    • getTenant lazily loads tenant if missing:
      • Uses config.modules.getConfigAdapter to read services.json from the configured configStore infra
      • Builds a Tenant (tenant.ts) and initializes services
    • For each request, ServiceFactory.getMessageFunctionByUrl selects the service by longest base-path match and returns a MessageFunction
  • Tenants and configuration (tenant.ts)

    • Builds servicesConfig from raw services.json plus chords (composable config fragments)
    • Applies defaults and config templates from service manifests before initialization
    • Splits “local vs remote” sources to ensure local HTTP sources are ready first (readyBasePaths gating)
    • Attaches the auth service (if present) and uses it to set msg.user
  • Manifests, services, and adapters

    • services/ contains built-in services; each has a manifest (.rsm.js) and implementation (.ts)
    • Adapters in adapter/ expose infrastructure and have manifests (*.ram.js)
    • ServiceFactory loads manifests, ensures adapter manifests exist for infra, and validates service/adapter configs using schemasafe validation (via Modules.defaultValidator)
    • Private services: manifests can declare privateServices; ServiceFactory synthesizes configs with basePath="/*"
  • Service wrapper and pipelines

    • ServiceWrapper wraps Service.func to run pre and post pipelines (merge of manifest and service config), apply redirects, and then execute
    • External calls: applies CORS, auth checks (AuthorizationType), and caching/ETag logic
    • MIME handlers (mimeHandlers.ts) post-process messages by content type (e.g., directory listings, zip aggregation)
    • Pipelines (pipeline/pipeline.ts) parse and execute declarative pipeline specs with steps, transforms, modes, and parallelization operators
  • Modules and dynamic loading (Modules.ts)

    • Caches loaded services, adapters, and manifests keyed by canonical URLs
    • Statically wires core services/adapters, but can dynamically import additional modules from file or HTTP(S)
    • Validates manifests, generates per-source config validators from manifest schemas
  • Internal vs external requests

    • Internal requests (Source.Internal/Outer) never hit the network; routing re-enters ServiceFactory and respects private services
    • External requests fall back to fetch unless overridden by config.requestExternal (used in tests)
  • Testing approach (test/)

    • testServerConfig.ts sets a local disk-backed config store and test root path (C:\Dev\test\test-data${tenant})
    • testUtility.ts constructs Message objects, calls handleIncomingRequest directly, and can intercept external requests via sysConfig.requestExternal

Important references

  • README.md: overarching concepts and links to Restspace documentation, including the Technical Overview
  • services/README.md: how to author services/adapters, manifest fields, handler API, and state management

Notes for future automation

  • Prefer deno run with the appropriate import map for your setup (local core vs hosted core)
  • Tests assume Windows-specific test data paths; do not remove or alter C:\Dev\test unless intentional
  • Avoid remote deployment scripts that require local key paths; those are environment-specific and should not be run automatically