mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-31 04:23:40 +00:00
sdk comments
This commit is contained in:
@@ -1,3 +1,15 @@
|
||||
/**
|
||||
* @module Host
|
||||
*
|
||||
* This module provides the MultiHost class for binding network ports and
|
||||
* exposing service interfaces through the StartOS networking layer.
|
||||
*
|
||||
* MultiHost handles the complexity of:
|
||||
* - Port binding with protocol-specific defaults
|
||||
* - Automatic SSL/TLS setup for secure protocols
|
||||
* - Integration with Tor and LAN networking
|
||||
*/
|
||||
|
||||
import { object, string } from "ts-matches"
|
||||
import { Effects } from "../Effects"
|
||||
import { Origin } from "./Origin"
|
||||
@@ -8,37 +20,53 @@ import { AlpnInfo } from "../osBindings"
|
||||
|
||||
export { AddSslOptions, Security, BindOptions }
|
||||
|
||||
/**
|
||||
* Known protocol definitions with their default ports and SSL variants.
|
||||
*
|
||||
* Each protocol includes:
|
||||
* - `secure` - Whether the protocol is inherently secure (SSL/TLS)
|
||||
* - `defaultPort` - Standard port for this protocol
|
||||
* - `withSsl` - The SSL variant of the protocol (if applicable)
|
||||
* - `alpn` - ALPN negotiation info for TLS
|
||||
*/
|
||||
export const knownProtocols = {
|
||||
/** HTTP - plain text web traffic, auto-upgrades to HTTPS */
|
||||
http: {
|
||||
secure: null,
|
||||
defaultPort: 80,
|
||||
withSsl: "https",
|
||||
alpn: { specified: ["http/1.1"] } as AlpnInfo,
|
||||
},
|
||||
/** HTTPS - encrypted web traffic */
|
||||
https: {
|
||||
secure: { ssl: true },
|
||||
defaultPort: 443,
|
||||
},
|
||||
/** WebSocket - plain text, auto-upgrades to WSS */
|
||||
ws: {
|
||||
secure: null,
|
||||
defaultPort: 80,
|
||||
withSsl: "wss",
|
||||
alpn: { specified: ["http/1.1"] } as AlpnInfo,
|
||||
},
|
||||
/** Secure WebSocket */
|
||||
wss: {
|
||||
secure: { ssl: true },
|
||||
defaultPort: 443,
|
||||
},
|
||||
/** SSH - inherently secure (no SSL wrapper needed) */
|
||||
ssh: {
|
||||
secure: { ssl: false },
|
||||
defaultPort: 22,
|
||||
},
|
||||
/** DNS - domain name service */
|
||||
dns: {
|
||||
secure: { ssl: false },
|
||||
defaultPort: 53,
|
||||
},
|
||||
} as const
|
||||
|
||||
/** Protocol scheme string or null for no scheme */
|
||||
export type Scheme = string | null
|
||||
|
||||
type KnownProtocols = typeof knownProtocols
|
||||
@@ -69,14 +97,47 @@ export type BindOptionsByProtocol =
|
||||
| BindOptionsByKnownProtocol
|
||||
| (BindOptions & { protocol: null })
|
||||
|
||||
/** @internal Helper to detect if protocol is a known protocol string */
|
||||
const hasStringProtocol = object({
|
||||
protocol: string,
|
||||
}).test
|
||||
|
||||
/**
|
||||
* Manages network bindings for a service interface.
|
||||
*
|
||||
* MultiHost is the primary way to expose your service's ports to users.
|
||||
* It handles:
|
||||
* - Port binding with the StartOS networking layer
|
||||
* - Protocol-aware defaults (HTTP uses port 80, HTTPS uses 443, etc.)
|
||||
* - Automatic SSL certificate provisioning for secure protocols
|
||||
* - Creation of Origin objects for exporting service interfaces
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* // Create a host for the web UI
|
||||
* const webHost = sdk.MultiHost.of(effects, 'webui')
|
||||
*
|
||||
* // Bind port 3000 with HTTP (automatically adds HTTPS variant)
|
||||
* const webOrigin = await webHost.bindPort(3000, { protocol: 'http' })
|
||||
*
|
||||
* // Export the interface
|
||||
* await webOrigin.export([
|
||||
* sdk.ServiceInterfaceBuilder.of({
|
||||
* effects,
|
||||
* name: 'Web Interface',
|
||||
* id: 'webui',
|
||||
* description: 'Access the dashboard',
|
||||
* type: 'ui',
|
||||
* })
|
||||
* ])
|
||||
* ```
|
||||
*/
|
||||
export class MultiHost {
|
||||
constructor(
|
||||
readonly options: {
|
||||
/** Effects instance for system operations */
|
||||
effects: Effects
|
||||
/** Unique identifier for this host binding */
|
||||
id: string
|
||||
},
|
||||
) {}
|
||||
|
||||
@@ -1,16 +1,66 @@
|
||||
/**
|
||||
* @module Origin
|
||||
*
|
||||
* The Origin class represents a bound network origin (protocol + host + port)
|
||||
* that can be used to export service interfaces.
|
||||
*/
|
||||
|
||||
import { AddressInfo } from "../types"
|
||||
import { AddressReceipt } from "./AddressReceipt"
|
||||
import { MultiHost, Scheme } from "./Host"
|
||||
import { ServiceInterfaceBuilder } from "./ServiceInterfaceBuilder"
|
||||
|
||||
/**
|
||||
* Represents a network origin (protocol://host:port) created from a MultiHost binding.
|
||||
*
|
||||
* Origins are created by calling `MultiHost.bindPort()` and can be used to
|
||||
* export one or more service interfaces that share the same underlying connection.
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* // Create origin from host binding
|
||||
* const origin = await webHost.bindPort(8080, { protocol: 'http' })
|
||||
*
|
||||
* // Export multiple interfaces sharing this origin
|
||||
* await origin.export([
|
||||
* sdk.ServiceInterfaceBuilder.of({
|
||||
* effects,
|
||||
* name: 'Web UI',
|
||||
* id: 'ui',
|
||||
* type: 'ui',
|
||||
* description: 'Main web interface',
|
||||
* }),
|
||||
* sdk.ServiceInterfaceBuilder.of({
|
||||
* effects,
|
||||
* name: 'REST API',
|
||||
* id: 'api',
|
||||
* type: 'api',
|
||||
* description: 'JSON API endpoint',
|
||||
* path: '/api/v1',
|
||||
* }),
|
||||
* ])
|
||||
* ```
|
||||
*/
|
||||
export class Origin {
|
||||
constructor(
|
||||
/** The MultiHost this origin was created from */
|
||||
readonly host: MultiHost,
|
||||
/** The internal port this origin is bound to */
|
||||
readonly internalPort: number,
|
||||
/** The protocol scheme (e.g., "http", "ssh") or null */
|
||||
readonly scheme: string | null,
|
||||
/** The SSL variant scheme (e.g., "https", "wss") or null */
|
||||
readonly sslScheme: string | null,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Builds an AddressInfo object for this origin with the specified options.
|
||||
* Used internally by `export()` but can be called directly for custom use cases.
|
||||
*
|
||||
* @param options - Build options including path, query params, username, and scheme overrides
|
||||
* @returns AddressInfo object describing the complete address
|
||||
* @internal
|
||||
*/
|
||||
build({
|
||||
username,
|
||||
path,
|
||||
@@ -36,12 +86,28 @@ export class Origin {
|
||||
}
|
||||
|
||||
/**
|
||||
* @description A function to register a group of origins (<PROTOCOL> :// <HOSTNAME> : <PORT>) with StartOS
|
||||
* Exports one or more service interfaces for this origin.
|
||||
*
|
||||
* The returned addressReceipt serves as proof that the addresses were registered
|
||||
* Each service interface becomes a clickable link in the StartOS UI.
|
||||
* Multiple interfaces can share the same origin but have different
|
||||
* names, descriptions, types, paths, or query parameters.
|
||||
*
|
||||
* @param addressInfo
|
||||
* @returns
|
||||
* @param serviceInterfaces - Array of ServiceInterfaceBuilder objects to export
|
||||
* @returns Promise resolving to array of AddressInfo with an AddressReceipt
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* await origin.export([
|
||||
* sdk.ServiceInterfaceBuilder.of({
|
||||
* effects,
|
||||
* name: 'Admin Panel',
|
||||
* id: 'admin',
|
||||
* type: 'ui',
|
||||
* description: 'Administrator dashboard',
|
||||
* path: '/admin',
|
||||
* })
|
||||
* ])
|
||||
* ```
|
||||
*/
|
||||
async export(
|
||||
serviceInterfaces: ServiceInterfaceBuilder[],
|
||||
@@ -83,9 +149,17 @@ export class Origin {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for building an address from an Origin.
|
||||
* @internal
|
||||
*/
|
||||
type BuildOptions = {
|
||||
/** Override the default schemes for SSL and non-SSL connections */
|
||||
schemeOverride: { ssl: Scheme; noSsl: Scheme } | null
|
||||
/** Optional username for basic auth URLs */
|
||||
username: string | null
|
||||
/** URL path (e.g., "/api/v1") */
|
||||
path: string
|
||||
/** Query parameters to append to the URL */
|
||||
query: Record<string, string>
|
||||
}
|
||||
|
||||
@@ -1,30 +1,86 @@
|
||||
/**
|
||||
* @module ServiceInterfaceBuilder
|
||||
*
|
||||
* Provides the ServiceInterfaceBuilder class for creating service interface
|
||||
* configurations that are exported to the StartOS UI.
|
||||
*/
|
||||
|
||||
import { ServiceInterfaceType } from "../types"
|
||||
import { Effects } from "../Effects"
|
||||
import { Scheme } from "./Host"
|
||||
|
||||
/**
|
||||
* A helper class for creating a Network Interface
|
||||
* Builder class for creating service interface configurations.
|
||||
*
|
||||
* Network Interfaces are collections of web addresses that expose the same API or other resource,
|
||||
* display to the user with under a common name and description.
|
||||
* A service interface represents a user-visible endpoint in the StartOS UI.
|
||||
* It appears as a clickable link that users can use to access your service's
|
||||
* web UI, API, or other network resources.
|
||||
*
|
||||
* All URIs on an interface inherit the same ui: bool, basic auth credentials, path, and search (query) params
|
||||
* Interfaces are created with this builder and then exported via `Origin.export()`.
|
||||
*
|
||||
* @param options
|
||||
* @returns
|
||||
* @example
|
||||
* ```typescript
|
||||
* // Create a basic web UI interface
|
||||
* const webInterface = sdk.ServiceInterfaceBuilder.of({
|
||||
* effects,
|
||||
* name: 'Web Interface',
|
||||
* id: 'webui',
|
||||
* description: 'Access the main web dashboard',
|
||||
* type: 'ui',
|
||||
* })
|
||||
*
|
||||
* // Create an API interface with a specific path
|
||||
* const apiInterface = sdk.ServiceInterfaceBuilder.of({
|
||||
* effects,
|
||||
* name: 'REST API',
|
||||
* id: 'api',
|
||||
* description: 'JSON API for programmatic access',
|
||||
* type: 'api',
|
||||
* path: '/api/v1',
|
||||
* })
|
||||
*
|
||||
* // Create an interface with basic auth
|
||||
* const protectedInterface = sdk.ServiceInterfaceBuilder.of({
|
||||
* effects,
|
||||
* name: 'Admin Panel',
|
||||
* id: 'admin',
|
||||
* description: 'Protected admin area',
|
||||
* type: 'ui',
|
||||
* username: 'admin',
|
||||
* masked: true, // Hide the URL from casual viewing
|
||||
* })
|
||||
*
|
||||
* // Export all interfaces on the same origin
|
||||
* await origin.export([webInterface, apiInterface, protectedInterface])
|
||||
* ```
|
||||
*/
|
||||
export class ServiceInterfaceBuilder {
|
||||
constructor(
|
||||
readonly options: {
|
||||
/** Effects instance for system operations */
|
||||
effects: Effects
|
||||
/** Display name shown in the StartOS UI */
|
||||
name: string
|
||||
/** Unique identifier for this interface */
|
||||
id: string
|
||||
/** Description shown below the interface name */
|
||||
description: string
|
||||
/**
|
||||
* Type of interface:
|
||||
* - `"ui"` - Web interface (opens in browser)
|
||||
* - `"api"` - API endpoint (for programmatic access)
|
||||
* - `"p2p"` - Peer-to-peer endpoint (e.g., Bitcoin P2P)
|
||||
*/
|
||||
type: ServiceInterfaceType
|
||||
/** Username for basic auth URLs (null for no auth) */
|
||||
username: string | null
|
||||
/** URL path to append (e.g., "/admin", "/api/v1") */
|
||||
path: string
|
||||
/** Query parameters to append to the URL */
|
||||
query: Record<string, string>
|
||||
/** Override default protocol schemes */
|
||||
schemeOverride: { ssl: Scheme; noSsl: Scheme } | null
|
||||
/** If true, the URL is hidden/masked in the UI (for sensitive endpoints) */
|
||||
masked: boolean
|
||||
},
|
||||
) {}
|
||||
|
||||
@@ -1,20 +1,84 @@
|
||||
/**
|
||||
* @module setupInterfaces
|
||||
*
|
||||
* This module provides utilities for setting up network interfaces (service endpoints)
|
||||
* that are exposed to users through the StartOS UI.
|
||||
*
|
||||
* Service interfaces are the clickable links users see to access your service's
|
||||
* web UI, API endpoints, or peer-to-peer connections.
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* export const setInterfaces = sdk.setupInterfaces(async ({ effects }) => {
|
||||
* const webHost = sdk.MultiHost.of(effects, 'webui')
|
||||
* const webOrigin = await webHost.bindPort(8080, { protocol: 'http' })
|
||||
*
|
||||
* await webOrigin.export([
|
||||
* sdk.ServiceInterfaceBuilder.of({
|
||||
* effects,
|
||||
* name: 'Web Interface',
|
||||
* id: 'webui',
|
||||
* description: 'Access the web dashboard',
|
||||
* type: 'ui',
|
||||
* })
|
||||
* ])
|
||||
*
|
||||
* return [webOrigin]
|
||||
* })
|
||||
* ```
|
||||
*/
|
||||
|
||||
import * as T from "../types"
|
||||
import { once } from "../util"
|
||||
import { AddressReceipt } from "./AddressReceipt"
|
||||
|
||||
/** @internal Type brand for interface update receipt */
|
||||
declare const UpdateServiceInterfacesProof: unique symbol
|
||||
|
||||
/**
|
||||
* Receipt type proving that service interfaces have been updated.
|
||||
* @internal
|
||||
*/
|
||||
export type UpdateServiceInterfacesReceipt = {
|
||||
[UpdateServiceInterfacesProof]: never
|
||||
}
|
||||
|
||||
/** Array of address info arrays with receipts, representing all exported interfaces */
|
||||
export type ServiceInterfacesReceipt = Array<T.AddressInfo[] & AddressReceipt>
|
||||
|
||||
/**
|
||||
* Function type for setting up service interfaces.
|
||||
* @typeParam Output - The specific receipt type returned
|
||||
*/
|
||||
export type SetServiceInterfaces<Output extends ServiceInterfacesReceipt> =
|
||||
(opts: { effects: T.Effects }) => Promise<Output>
|
||||
|
||||
/** Function type for the init-compatible interface updater */
|
||||
export type UpdateServiceInterfaces = (effects: T.Effects) => Promise<null>
|
||||
|
||||
/** Function type for the setupServiceInterfaces helper */
|
||||
export type SetupServiceInterfaces = <Output extends ServiceInterfacesReceipt>(
|
||||
fn: SetServiceInterfaces<Output>,
|
||||
) => UpdateServiceInterfaces
|
||||
|
||||
/**
|
||||
* Constant indicating no interface changes are needed.
|
||||
* Use this as a return value when interfaces don't need to be updated.
|
||||
*/
|
||||
export const NO_INTERFACE_CHANGES = {} as UpdateServiceInterfacesReceipt
|
||||
|
||||
/**
|
||||
* Creates an interface setup function for use in the initialization pipeline.
|
||||
*
|
||||
* **Note:** This is exposed via `sdk.setupInterfaces`. See the SDK documentation
|
||||
* for full usage examples and parameter descriptions.
|
||||
*
|
||||
* Internally, this wrapper:
|
||||
* - Tracks all bindings and interfaces created during setup
|
||||
* - Automatically cleans up stale bindings/interfaces that weren't recreated
|
||||
*
|
||||
* @see sdk.setupInterfaces for usage documentation
|
||||
*/
|
||||
export const setupServiceInterfaces: SetupServiceInterfaces = <
|
||||
Output extends ServiceInterfacesReceipt,
|
||||
>(
|
||||
|
||||
Reference in New Issue
Block a user