@interopio/gateway
Version:
[](https://www.npmjs.com/package/@interopio/gateway)
321 lines (278 loc) • 10.9 kB
TypeScript
import { Metrics as IOGatewayMetrics } from './types/metrics/api';
import * as IOGatewayAuth from './types/auth/api';
import * as IOGatewayMesh from './types/mesh/api';
import * as IOGatewayLogging from './types/logging/core';
import { RestPublisherConfig } from './types/metrics/publisher/rest';
import { FilePublisherConfig } from './types/metrics/publisher/file';
import { CustomPublisherConfig } from './types/metrics/publisher/custom';
export default IOGateway.Factory;
export declare namespace IOGateway {
export const Factory: (options: GatewayConfig) => Gateway;
export type AuthenticatorConfig = {
timeout?: number
}
export type BasicAuthenticatorConfig = AuthenticatorConfig & {
/**
* Optional username resolver (async) function, used to map login to actual username.
*
* @param login
* @return resolved username
*/
usernameResolver?: (login?: string) => Promise<string> | string
/**
* Optional secret verifier function, used to validate username/password combinations.
* @param username
* @param password
*/
secretVerifier?: (username?: string, password?: string) => Promise<boolean>,
};
export type Oauth2AuthenticatorConfig = AuthenticatorConfig & {
/**
* Base url, used to find the authorization server's app metadata.
*/
issuerBaseURL?: string
/**
* Expected JWT "aud" claim value.
*/
audience?: string
}
export import Auth = IOGatewayAuth;
export type CustomAuthenticator = AuthenticatorConfig & {
authenticator: Auth.Authenticator
}
export type AuthenticationConfig = {
/**
* Default authentication provider if not specified by the client.
*/
default?: string
/**
* List of authentication providers to be used by the gateway
*/
available?: Exclude<string, 'default' | 'available'>[]
basic?: BasicAuthenticatorConfig
oauth2?: Oauth2AuthenticatorConfig
} | Partial<Record<Exclude<string, 'default' | 'available' | 'basic' | 'oauth2'>, CustomAuthenticator>>
export type BasicMetricsPublisherConfig = {
filters?: MetricFilters,
heartbeats?: number
buffer_size?: number
conflation?: {
'interval'?: number // default 1000
'max-size'?: number // default 0
'max-datapoints-repo'?: number
}
}
export type FileMetricsPublisherConfig = BasicMetricsPublisherConfig & FilePublisherConfig;
export type RestMetricsPublisherConfig = BasicMetricsPublisherConfig & RestPublisherConfig;
export type CustomMetricsPublisherConfig = BasicMetricsPublisherConfig & CustomPublisherConfig;
export import Metrics = IOGatewayMetrics;
export type MetricFilters = {
publishers: {
identity: Record<string, Filtering.Matcher>
metrics: {
allow?: Filtering.Matcher[]
block?: Filtering.Matcher[]
/**
* @deprecated
* @see allow
*/
whitelist?: Filtering.Matcher[]
/**
* @deprecated
* @see block
*/
blacklist?: Filtering.Matcher[]
}
}[],
non_matched?: Filtering.Action
}
export interface MetricPublishersConfig {
file: FileMetricsPublisherConfig
rest: RestMetricsPublisherConfig
}
export type MetricsConfig = {
publishers: ((keyof MetricPublishersConfig) | CustomMetricsPublisherConfig)[]
filters?: MetricFilters
} & Partial<MetricPublishersConfig>
export type MeshMember = Readonly<{ endpoint: string, node: string }>;
export type StaticMeshDirectoryConfig = { members: MeshMember[] };
export type RestMeshDirectoryConfig = { uri?: string, interval?: number, metadata?: { [key: string]: string } };
export type GlobalsConfig = {
WebSocket?: typeof WebSocket
URL?: typeof URL
URLSearchParams?: typeof URLSearchParams
fetch?: typeof fetch
Headers?: typeof Headers
// crypto?: typeof crypto
}
/**
* Gateway Mesh Configuration
*/
export type MeshConfig = {
/**
* Node id to be used for mesh. If not specified fallbacks to GatewayConfig#node.
*/
node?: string,
/**
* Authentication options for connecting to the mesh cluster.
*/
auth: MeshAuthConfig,
/**
*
*/
cluster?: MeshClusterConfig,
/**
* @ignore
*/
broker?: {
endpoint: string
},
/**
* @experimental
*/
channel?: IOGatewayMesh.MeshChannel
}
export type MeshAuthConfig = {
/**
* User(s) advertised to the mesh.
* If null is specified, then all users logged in the gateway are allowed (dynamically calculated).
* If not specified (undefined), then user is deduced from the credentials used to connect to the mesh, if possible.
*/
user?: null | string | string[],
} & (
{
basic?: {
username: string,
password: string
}
}
|
{
token?: {
type?: 'jwt',
value: string
},
})
export type MeshClusterConfig = {
endpoint: string,
relays?: string,
directory?: StaticMeshDirectoryConfig | RestMeshDirectoryConfig,
opts?: {
// for HTTP headers
headers?: Record<string, string>
// function to get dynamic headers per request (additional to static headers above)
getHeaders?: () => Record<string, string> | Promise<Record<string, string>>
// for some libraries (like browser WebSocket) headers are not supported at all
// of others (like node ws and undici (i.e. built-in NodeJs)) they are supported in the second param like new WebSocket(url, {headers})
// in case you need to set specific protocols for the WebSocket connection (this will go as a second param in the WebSocket constructor)
// depending on the WebSocket library you are using, this can be a string, array of strings or an object with protocols and headers
getWebSocketProtocols?: (headers?: Readonly<Record<string, string>>, protocols?: string | readonly string[]) => string | string[] | {
protocols?: string | string[],
headers?: Record<string, string>
},
// in case you need to add search params to the endpoint url, because headers are not supported (like in browser WebSocket)
getWebSocketSearchParams?: (headers?: Readonly<Record<string, string>>, search?: string) => Record<string, string | undefined> | undefined
} & Pick<GlobalsConfig, 'fetch' | 'WebSocket' | 'URL' | 'URLSearchParams'>
}
export type VisibilityRule<K extends string> = {
identity?: Record<string, Filtering.Matcher>
restrictions: 'local' | 'cluster'
} & (Partial<Record<K, Filtering.Matcher>>)
export type GatewayConfig = {
token?: {
ttl?: number
key?: string
},
authentication?: AuthenticationConfig
metrics?: MetricsConfig
node?: string,
contexts?: {
/**
* Default context lifetime.
* @experimental
* @default 'ref-counted'
*/
lifetime?: 'ref-counted' | 'ownership' | 'retained',
/**
* Default context visibility rules.
*/
visibility?: VisibilityRule<'context'>[]
},
methods?: {
/**
* Default method visibility rules.
*/
visibility?: VisibilityRule<'method'>[]
},
peers?: {
/**
* Default peer visibility.
*/
visibility?: VisibilityRule<'domain'>[]
}
clients?: {
inactive_seconds?: number,
buffer_size?: number
},
/**
* Mesh Configuration.
*/
mesh?: MeshConfig
globals?: GlobalsConfig
}
export interface Message<T = string> {
type: T
}
export type GatewayClientOptions<T> = {
key?: string,
codec?: Encoding.Codec<Message, T>
onAuthenticate?: (this: GatewayClient<T>, request: Auth.AuthenticationRequest) => Promise<Auth.AuthenticationSuccess>
onPing?: (this: GatewayClient<T>) => void
onDisconnect?: (this: GatewayClient<T>, reason: 'inactive' | 'shutdown') => void
};
export interface Gateway {
start(environment?: { endpoint?: string }): Promise<Gateway>
stop(): Promise<Gateway>
info(): Record<string, unknown>
client<T = Message>(handler: (this: GatewayClient<T>, msg: T) => void,
opts?: GatewayClientOptions<T>): GatewayClient<T>
connect(handler: (client: GatewayClient, msg: Message) => void): Promise<GatewayClient>
}
export interface GatewayClient<T = Message> {
send(msg: T): void
close(): void
}
export namespace Filtering {
export type ExactMatch = Omit<string, `#${string}` | `/${string}/`>;
export type RegexMatch = RegExp | `#${string}` | `/${string}/`;
export type Matcher = ExactMatch | RegExp;
export type Action
= 'allow' | 'block'
// cultural sensitive deprecated values
| 'whitelist' | 'blacklist';
export function regexify(expression: ExactMatch | RegexMatch): Matcher;
export function valueMatches(expression: Matcher, value?: unknown): boolean;
export function valuesMatch(expressions: Matcher[], value?: string): boolean;
}
export import Logging = IOGatewayLogging;
export namespace Encoding {
export type Codec<T, R> = {
encode: (msg: T) => R;
decode: (data: R) => T;
};
export type KeywordizeCommand
= '*' // keywordize for all string values for ex {:type :cluster}
| Set<string> // keywordize only specific values
| null // stop keywordization (even for keys)
;
export function transit<T>(opts?: {
keywordize?: Map<string, KeywordizeCommand>;
verbose?: boolean;
namespaces?: Map<string, string>;
}): Codec<T, string>;
export function json<T>(): Codec<T, string>;
export function direct<T>(opts?: {
cljs?: boolean
}): Codec<T, T>;
}
}