Files
recap/node_modules/@start9labs/start-sdk/base/lib/util/getServiceInterface.d.ts
T

186 lines
9.1 KiB
TypeScript

import { PackageId, ServiceInterfaceId, ServiceInterfaceType } from '../types';
import { AddressInfo, Host, Hostname, HostnameInfo } from '../types';
import { Effects } from '../Effects';
import { Watchable } from './Watchable';
export type UrlString = string;
export type HostId = string;
export declare const getHostname: (url: string) => Hostname | null;
/**
* The kinds of hostnames that can be filtered on.
*
* - `'mdns'` — mDNS / Bonjour `.local` hostnames
* - `'domain'` — any os-managed domain name (matches both `'private-domain'` and `'public-domain'` metadata kinds)
* - `'ip'` — shorthand for both `'ipv4'` and `'ipv6'`
* - `'ipv4'` — IPv4 addresses only
* - `'ipv6'` — IPv6 addresses only
* - `'localhost'` — loopback addresses (`localhost`, `127.0.0.1`, `::1`)
* - `'link-local'` — IPv6 link-local addresses (fe80::/10)
* - `'bridge'` — The LXC bridge interface
* - `'plugin'` — hostnames provided by a plugin package
*/
type FilterKinds = 'mdns' | 'domain' | 'ip' | 'ipv4' | 'ipv6' | 'localhost' | 'link-local' | 'bridge' | 'plugin';
/**
* Describes which hostnames to include (or exclude) when filtering a `Filled` address.
*
* Every field is optional — omitted fields impose no constraint.
* Filters are composable: the `.filter()` method intersects successive filters,
* and the `exclude` field inverts a nested filter.
*/
export type Filter = {
/** Keep only hostnames with the given visibility. `'public'` = externally reachable, `'private'` = LAN-only. */
visibility?: 'public' | 'private';
/** Keep only hostnames whose metadata kind matches. A single kind or array of kinds. `'ip'` expands to `['ipv4','ipv6']`, `'domain'` matches both `'private-domain'` and `'public-domain'`. */
kind?: FilterKinds | FilterKinds[];
/** Arbitrary predicate — hostnames for which this returns `false` are excluded. */
predicate?: (h: HostnameInfo) => boolean;
/** Keep only plugin hostnames provided by this package. Implies `kind: 'plugin'`. */
pluginId?: PackageId;
/** A nested filter whose matches are *removed* from the result (logical NOT). */
exclude?: Filter;
};
type VisibilityFilter<V extends 'public' | 'private'> = V extends 'public' ? (HostnameInfo & {
public: true;
}) | VisibilityFilter<Exclude<V, 'public'>> : V extends 'private' ? (HostnameInfo & {
public: false;
}) | VisibilityFilter<Exclude<V, 'private'>> : never;
type KindFilter<K extends FilterKinds> = K extends 'mdns' ? (HostnameInfo & {
metadata: {
kind: 'mdns';
};
}) | KindFilter<Exclude<K, 'mdns'>> : K extends 'domain' ? (HostnameInfo & {
metadata: {
kind: 'private-domain';
};
}) | (HostnameInfo & {
metadata: {
kind: 'public-domain';
};
}) | KindFilter<Exclude<K, 'domain'>> : K extends 'ipv4' ? (HostnameInfo & {
metadata: {
kind: 'ipv4';
};
}) | KindFilter<Exclude<K, 'ipv4'>> : K extends 'ipv6' ? (HostnameInfo & {
metadata: {
kind: 'ipv6';
};
}) | KindFilter<Exclude<K, 'ipv6'>> : K extends 'plugin' ? (HostnameInfo & {
metadata: {
kind: 'plugin';
};
}) | KindFilter<Exclude<K, 'plugin'>> : K extends 'ip' ? KindFilter<Exclude<K, 'ip'> | 'ipv4' | 'ipv6'> : never;
type FilterReturnTy<F extends Filter> = F extends {
visibility: infer V extends 'public' | 'private';
} ? VisibilityFilter<V> & FilterReturnTy<Omit<F, 'visibility'>> : F extends {
kind: (infer K extends FilterKinds) | (infer K extends FilterKinds)[];
} ? KindFilter<K> & FilterReturnTy<Omit<F, 'kind'>> : F extends {
predicate: (h: HostnameInfo) => h is infer H extends HostnameInfo;
} ? H & FilterReturnTy<Omit<F, 'predicate'>> : F extends {
exclude: infer E extends Filter;
} ? HostnameInfo extends FilterReturnTy<E> ? HostnameInfo : Exclude<HostnameInfo, FilterReturnTy<E>> : HostnameInfo;
declare const nonLocalFilter: {
readonly exclude: {
readonly kind: ("localhost" | "link-local" | "bridge")[];
};
};
declare const publicFilter: {
readonly visibility: "public";
};
type Formats = 'hostname-info' | 'urlstring' | 'url';
type FormatReturnTy<F extends Filter, Format extends Formats> = Format extends 'hostname-info' ? FilterReturnTy<F> | FormatReturnTy<F, Exclude<Format, 'hostname-info'>> : Format extends 'url' ? URL | FormatReturnTy<F, Exclude<Format, 'url'>> : Format extends 'urlstring' ? UrlString | FormatReturnTy<F, Exclude<Format, 'urlstring'>> : never;
/**
* A resolved address with its hostnames already populated, plus helpers
* for filtering, formatting, and converting hostnames to URLs.
*
* Filters are chainable and each call returns a new `Filled` narrowed to the
* matching subset of hostnames:
*
* ```ts
* addresses.nonLocal // exclude localhost & link-local
* addresses.public // only publicly-reachable hostnames
* addresses.filter({ kind: 'domain' }) // only domain-name hostnames
* addresses.filter({ visibility: 'private' }) // only LAN-reachable hostnames
* addresses.nonLocal.filter({ kind: 'ip' }) // chainable — non-local IPs only
* ```
*/
export type Filled<F extends Filter = {}> = {
/** The hostnames that survived all applied filters. */
hostnames: HostnameInfo[];
/** Convert a single hostname into a fully-formed URL string, applying the address's scheme, username, and suffix. */
toUrl: (h: HostnameInfo) => UrlString;
/**
* Return every hostname in the requested format.
*
* - `'urlstring'` (default) — formatted URL strings
* - `'url'` — `URL` objects
* - `'hostname-info'` — raw `HostnameInfo` objects
*/
format: <Format extends Formats = 'urlstring'>(format?: Format) => FormatReturnTy<{}, Format>[];
/**
* Apply an arbitrary {@link Filter} and return a new `Filled` containing only
* the hostnames that match. Filters compose: calling `.filter()` on an
* already-filtered `Filled` intersects the constraints.
*/
filter: <NewFilter extends Filter>(filter: NewFilter) => Filled<NewFilter & Filter>;
/**
* Apply multiple filters and return hostnames that match **any** of them (union / OR).
*
* ```ts
* addresses.matchesAny([{ kind: 'domain' }, { kind: 'mdns' }])
* ```
*/
matchesAny: <NewFilters extends Filter[]>(filters: [...NewFilters]) => Filled<NewFilters[number] & F>;
/** Shorthand filter that excludes `localhost` and IPv6 link-local addresses — keeps only network-reachable hostnames. */
nonLocal: Filled<typeof nonLocalFilter & Filter>;
/** Shorthand filter that keeps only publicly-reachable hostnames (those with `public: true`). */
public: Filled<typeof publicFilter & Filter>;
};
export type FilledAddressInfo = AddressInfo & Filled;
export type ServiceInterfaceFilled = {
id: string;
/** The title of this field to be displayed */
name: string;
/** Human readable description, used as tooltip usually */
description: string;
/** Whether or not to mask the URIs for this interface. Useful if the URIs contain sensitive information, such as a password, macaroon, or API key */
masked: boolean;
/** Information about the host for this binding */
host: Host | null;
/** URI information */
addressInfo: FilledAddressInfo | null;
/** Indicates if we are a ui/p2p/api for the kind of interface that this is representing */
type: ServiceInterfaceType;
};
export declare const addressHostToUrl: ({ scheme, sslScheme, username, suffix }: AddressInfo, hostname: HostnameInfo) => UrlString;
/**
* Filters out localhost and IPv6 link-local hostnames from a list.
* Equivalent to the `nonLocal` filter on `Filled` addresses.
*/
export declare function filterNonLocal(hostnames: HostnameInfo[]): HostnameInfo[];
export declare const filledAddress: (host: Host, addressInfo: AddressInfo) => FilledAddressInfo;
export declare class GetServiceInterface<Mapped = ServiceInterfaceFilled | null> extends Watchable<ServiceInterfaceFilled | null, Mapped> {
readonly opts: {
id: string;
packageId?: string;
};
protected readonly label = "GetServiceInterface";
constructor(effects: Effects, opts: {
id: string;
packageId?: string;
}, options?: {
map?: (value: ServiceInterfaceFilled | null) => Mapped;
eq?: (a: Mapped, b: Mapped) => boolean;
});
protected fetch(callback?: () => void): Promise<ServiceInterfaceFilled | null>;
}
export declare function getOwnServiceInterface(effects: Effects, id: ServiceInterfaceId): GetServiceInterface;
export declare function getOwnServiceInterface<Mapped>(effects: Effects, id: ServiceInterfaceId, map: (interfaces: ServiceInterfaceFilled | null) => Mapped, eq?: (a: Mapped, b: Mapped) => boolean): GetServiceInterface<Mapped>;
export declare function getServiceInterface(effects: Effects, opts: {
id: ServiceInterfaceId;
packageId: PackageId;
}): GetServiceInterface;
export declare function getServiceInterface<Mapped>(effects: Effects, opts: {
id: ServiceInterfaceId;
packageId: PackageId;
}, map: (interfaces: ServiceInterfaceFilled | null) => Mapped, eq?: (a: Mapped, b: Mapped) => boolean): GetServiceInterface<Mapped>;
export {};