UNPKG

@k8ts/instruments

Version:

A collection of utilities and core components for k8ts.

103 lines (93 loc) 3.37 kB
import { Meta } from "@k8ts/metadata" import { Map } from "immutable" import { PortError } from "./error" import { PortMap } from "./map" import { parsePortInput, portRecordInput } from "./tools/entry" import type { InputPort, InputPortMapping, InputPortSetEntry, InputPortSetRecord, InputProtocol, PortSetEntry } from "./types" declare const __NAMES__: unique symbol export class PortSet<Names extends string = never> { constructor(private readonly _map: Map<Names, PortSetEntry> = Map()) { for (const entry of _map.values()) { Meta._checkNameValue(`container port '${entry.name}' (${entry.port})`, entry.name) } } private _apply(f: (map: Map<string, PortSetEntry>) => Map<string, PortSetEntry>) { return new PortSet(f(this._map)) } union<InNames extends string>(other: PortSet<InNames>): PortSet<Names | InNames> { return new PortSet(this._map.merge(other._map)) } add<Name extends string>( name: Name, port: InputPort, protocol: InputProtocol ): PortSet<Names | Name> add<Name extends string>(name: Name, entry: InputPortSetEntry): PortSet<Names | Name> add<InNames extends string>(input?: InputPortSetRecord<InNames>): PortSet<Names | InNames> add(a: any, b?: any, c?: any): any { if (!a) { return this } if (c) { return this._apply(map => map.set(a, { name: a, port: +b, protocol: c.toUpperCase() })) } if (b) { return this._apply(map => map.set(a, parsePortInput(a, b))) } return this._apply(map => { const processed = portRecordInput(a) return map.merge(processed) }) } pick<InNames extends Names>(...name: InNames[]): PortSet<InNames> { return this._apply(map => map.filter((_, key) => name.includes(key as InNames))) as any } get names() { return this._map.keySeq().toArray() as Names[] } get(name: Names): PortSetEntry { if (!this._map.has(name)) { throw new PortError(`Port ${name} not found`) } return this._map.get(name)! } get values() { return this._map } map(mapping: InputPortMapping<Names>): PortMap<Names> { return new PortMap( this._map.map(entry => { if (!(entry.name in mapping)) { throw new PortError(`Port ${entry.name} not found in mapping`) } const portIn = mapping[entry.name as keyof typeof mapping] let portVal: number if (typeof portIn === "boolean") { portVal = entry.port } else if (typeof portIn === "number") { portVal = portIn } else { throw new PortError( `Port ${entry.name} mapping value must be a number or boolean` ) } return { name: entry.name, protocol: entry.protocol, backend: entry.name, frontend: portVal as any } }) ) } static make<Names extends string>(input?: InputPortSetRecord<Names>) { return new PortSet().add(input) } }