mirror of
https://github.com/Start9Labs/start-sdk.git
synced 2026-03-26 02:11:56 +00:00
feat: Add in the features for the utils.networkInterface.get
This commit is contained in:
@@ -64,8 +64,8 @@ export class Variants<Type, Store, Vault> {
|
||||
spec: Config<any, Store, Vault> | Config<any, never, never>
|
||||
}
|
||||
},
|
||||
Store,
|
||||
Vault,
|
||||
Store = never,
|
||||
Vault = never,
|
||||
>(a: VariantValues) {
|
||||
const validator = anyOf(
|
||||
...Object.entries(a).map(([name, { spec }]) =>
|
||||
|
||||
@@ -42,11 +42,11 @@ export class NetworkInterfaceBuilder {
|
||||
const { name, description, id, ui, username, path, search } = this.options
|
||||
|
||||
const addresses = Array.from(origins).map((o) =>
|
||||
o.build({ username, path, search }),
|
||||
o.build({ username, path, search, scheme: null }),
|
||||
)
|
||||
|
||||
await this.options.effects.exportNetworkInterface({
|
||||
id,
|
||||
interfaceId: id,
|
||||
name,
|
||||
description,
|
||||
addresses,
|
||||
|
||||
@@ -18,11 +18,13 @@ export class Origin<T extends Host> {
|
||||
options: this.options,
|
||||
suffix: `${path}${qp}`,
|
||||
username,
|
||||
scheme: this.options.scheme,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type BuildOptions = {
|
||||
scheme: string | null
|
||||
username: string | null
|
||||
path: string
|
||||
search: Record<string, string>
|
||||
|
||||
54
lib/types.ts
54
lib/types.ts
@@ -166,17 +166,21 @@ export type ActionMetadata = {
|
||||
*/
|
||||
group?: string
|
||||
}
|
||||
|
||||
export declare const hostName: unique symbol
|
||||
export type HostName = string & { [hostName]: never }
|
||||
/** ${scheme}://${username}@${host}:${externalPort}${suffix} */
|
||||
export type Address = {
|
||||
username: string | null
|
||||
hostId: string
|
||||
options: PortOptions
|
||||
suffix: string
|
||||
scheme: string | null
|
||||
}
|
||||
|
||||
export type InterfaceId = string
|
||||
|
||||
export type NetworkInterface = {
|
||||
id: string
|
||||
interfaceId: InterfaceId
|
||||
/** The title of this field to be displayed */
|
||||
name: string
|
||||
/** Human readable description, used as tooltip usually */
|
||||
@@ -188,19 +192,6 @@ export type NetworkInterface = {
|
||||
*/
|
||||
ui?: boolean
|
||||
}
|
||||
export type NetworkInterfaceOut = {
|
||||
id: string
|
||||
/** The title of this field to be displayed */
|
||||
name: string
|
||||
/** Human readable description, used as tooltip usually */
|
||||
description: string
|
||||
/** All URIs */
|
||||
addresses: string[]
|
||||
/** Defaults to false, but describes if this address can be opened in a browser as an
|
||||
* ui interface
|
||||
*/
|
||||
ui?: boolean
|
||||
}
|
||||
|
||||
/** Used to reach out from the pure js runtime */
|
||||
export type Effects = {
|
||||
@@ -240,11 +231,18 @@ export type Effects = {
|
||||
} & PortOptions,
|
||||
): Promise<void>
|
||||
/** Retrieves the current hostname(s) associated with a host id */
|
||||
getHostNames(options: {
|
||||
getHostnames(options: {
|
||||
kind: "static" | "single"
|
||||
id: string
|
||||
}): Promise<[string]>
|
||||
getHostNames(options: { kind: "multi"; id: string }): Promise<string[]>
|
||||
hostId: string
|
||||
packageId?: string
|
||||
callback: () => void
|
||||
}): Promise<[HostName]>
|
||||
getHostnames(options: {
|
||||
kind?: "multi"
|
||||
packageId?: string
|
||||
hostId: string
|
||||
callback: () => void
|
||||
}): Promise<[HostName, ...HostName[]]>
|
||||
|
||||
/** Similar to the fetch api via the mdn, this is simplified but the point is
|
||||
* to get something from some website, and return the response.
|
||||
@@ -310,7 +308,7 @@ export type Effects = {
|
||||
getIPHostname(): Promise<string[]>
|
||||
/** Get the address for another service for tor interfaces */
|
||||
getServiceTorHostname(
|
||||
interfaceId: string,
|
||||
interfaceId: InterfaceId,
|
||||
packageId?: string,
|
||||
): Promise<string>
|
||||
/** Get the IP address of the container */
|
||||
@@ -338,8 +336,20 @@ export type Effects = {
|
||||
*/
|
||||
getInterface(options: {
|
||||
packageId?: PackageId
|
||||
interfaceId: string
|
||||
}): Promise<NetworkInterfaceOut>
|
||||
interfaceId: InterfaceId
|
||||
callback: () => void
|
||||
}): Promise<NetworkInterface>
|
||||
|
||||
/**
|
||||
* There are times that we want to see the addresses that where exported
|
||||
* @param options.addressId If we want to filter the address id
|
||||
*
|
||||
* Note: any auth should be filtered out already
|
||||
*/
|
||||
listInterface(options: {
|
||||
packageId?: PackageId
|
||||
callback: () => void
|
||||
}): Promise<NetworkInterface[]>
|
||||
|
||||
/**
|
||||
*Remove an address that was exported. Used problably during main or during setConfig.
|
||||
|
||||
284
lib/util/getNetworkInterface.ts
Normal file
284
lib/util/getNetworkInterface.ts
Normal file
@@ -0,0 +1,284 @@
|
||||
import {
|
||||
Address,
|
||||
Effects,
|
||||
EnsureStorePath,
|
||||
HostName,
|
||||
NetworkInterface,
|
||||
hostName,
|
||||
} from "../types"
|
||||
import * as regexes from "./regexes"
|
||||
|
||||
export type UrlString = string
|
||||
export type HostId = string
|
||||
|
||||
export type Filled = {
|
||||
hostnames: HostName[]
|
||||
onionHostnames: HostName[]
|
||||
localHostnames: HostName[]
|
||||
ipHostnames: HostName[]
|
||||
ipv4Hostnames: HostName[]
|
||||
ipv6Hostnames: HostName[]
|
||||
nonIpHostnames: HostName[]
|
||||
allHostnames: HostName[]
|
||||
|
||||
urls: UrlString[]
|
||||
onionUrls: UrlString[]
|
||||
localUrls: UrlString[]
|
||||
ipUrls: UrlString[]
|
||||
ipv4Urls: UrlString[]
|
||||
ipv6Urls: UrlString[]
|
||||
nonIpUrls: UrlString[]
|
||||
allUrls: UrlString[]
|
||||
}
|
||||
export type FilledAddress = Address & Filled
|
||||
export type NetworkInterfaceFilled = {
|
||||
interfaceId: string
|
||||
/** The title of this field to be displayed */
|
||||
name: string
|
||||
/** Human readable description, used as tooltip usually */
|
||||
description: string
|
||||
/** All URIs */
|
||||
addresses: FilledAddress[]
|
||||
/** Defaults to false, but describes if this address can be opened in a browser as an
|
||||
* ui interface
|
||||
*/
|
||||
ui?: boolean
|
||||
} & Filled
|
||||
const either =
|
||||
<A>(...args: ((a: A) => boolean)[]) =>
|
||||
(a: A) =>
|
||||
args.some((x) => x(a))
|
||||
const negate =
|
||||
<A>(fn: (a: A) => boolean) =>
|
||||
(a: A) =>
|
||||
!fn(a)
|
||||
const unique = <A>(values: A[]) => Array.from(new Set(values))
|
||||
const addressHostToUrl = (
|
||||
{ scheme, username, suffix }: Address,
|
||||
host: HostName,
|
||||
): UrlString =>
|
||||
`${scheme ? `${scheme}//` : ""}${
|
||||
username ? `${username}@` : ""
|
||||
}${host}${suffix}`
|
||||
export const filledAddress = (
|
||||
mapHostnames: {
|
||||
[hostId: string]: HostName[]
|
||||
},
|
||||
address: Address,
|
||||
): FilledAddress => {
|
||||
const toUrl = addressHostToUrl.bind(null, address)
|
||||
const hostnames = mapHostnames[address.hostId] ?? []
|
||||
return {
|
||||
...address,
|
||||
hostnames,
|
||||
get onionHostnames() {
|
||||
return hostnames.filter(regexes.onionHost.test)
|
||||
},
|
||||
get localHostnames() {
|
||||
return hostnames.filter(regexes.localHost.test)
|
||||
},
|
||||
get ipHostnames() {
|
||||
return hostnames.filter(either(regexes.ipv4.test, regexes.ipv6.test))
|
||||
},
|
||||
get ipv4Hostnames() {
|
||||
return hostnames.filter(regexes.ipv4.test)
|
||||
},
|
||||
get ipv6Hostnames() {
|
||||
return hostnames.filter(regexes.ipv6.test)
|
||||
},
|
||||
get nonIpHostnames() {
|
||||
return hostnames.filter(
|
||||
negate(either(regexes.ipv4.test, regexes.ipv6.test)),
|
||||
)
|
||||
},
|
||||
allHostnames: hostnames,
|
||||
get urls() {
|
||||
return hostnames.map(toUrl)
|
||||
},
|
||||
get onionUrls() {
|
||||
return hostnames.filter(regexes.onionHost.test).map(toUrl)
|
||||
},
|
||||
get localUrls() {
|
||||
return hostnames.filter(regexes.localHost.test).map(toUrl)
|
||||
},
|
||||
get ipUrls() {
|
||||
return hostnames
|
||||
.filter(either(regexes.ipv4.test, regexes.ipv6.test))
|
||||
.map(toUrl)
|
||||
},
|
||||
get ipv4Urls() {
|
||||
return hostnames.filter(regexes.ipv4.test).map(toUrl)
|
||||
},
|
||||
get ipv6Urls() {
|
||||
return hostnames.filter(regexes.ipv6.test).map(toUrl)
|
||||
},
|
||||
get nonIpUrls() {
|
||||
return hostnames
|
||||
.filter(negate(either(regexes.ipv4.test, regexes.ipv6.test)))
|
||||
.map(toUrl)
|
||||
},
|
||||
get allUrls() {
|
||||
return hostnames.map(toUrl)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export const networkInterfaceFilled = (
|
||||
interfaceValue: NetworkInterface,
|
||||
addresses: FilledAddress[],
|
||||
): NetworkInterfaceFilled => {
|
||||
return {
|
||||
...interfaceValue,
|
||||
addresses,
|
||||
get hostnames() {
|
||||
return unique(addresses.flatMap((x) => x.hostnames))
|
||||
},
|
||||
get onionHostnames() {
|
||||
return unique(addresses.flatMap((x) => x.onionHostnames))
|
||||
},
|
||||
get localHostnames() {
|
||||
return unique(addresses.flatMap((x) => x.localHostnames))
|
||||
},
|
||||
get ipHostnames() {
|
||||
return unique(addresses.flatMap((x) => x.ipHostnames))
|
||||
},
|
||||
get ipv4Hostnames() {
|
||||
return unique(addresses.flatMap((x) => x.ipv4Hostnames))
|
||||
},
|
||||
get ipv6Hostnames() {
|
||||
return unique(addresses.flatMap((x) => x.ipv6Hostnames))
|
||||
},
|
||||
get nonIpHostnames() {
|
||||
return unique(addresses.flatMap((x) => x.nonIpHostnames))
|
||||
},
|
||||
get allHostnames() {
|
||||
return unique(addresses.flatMap((x) => x.allHostnames))
|
||||
},
|
||||
get urls() {
|
||||
return unique(addresses.flatMap((x) => x.urls))
|
||||
},
|
||||
get onionUrls() {
|
||||
return unique(addresses.flatMap((x) => x.onionUrls))
|
||||
},
|
||||
get localUrls() {
|
||||
return unique(addresses.flatMap((x) => x.localUrls))
|
||||
},
|
||||
get ipUrls() {
|
||||
return unique(addresses.flatMap((x) => x.ipUrls))
|
||||
},
|
||||
get ipv4Urls() {
|
||||
return unique(addresses.flatMap((x) => x.ipv4Urls))
|
||||
},
|
||||
get ipv6Urls() {
|
||||
return unique(addresses.flatMap((x) => x.ipv6Urls))
|
||||
},
|
||||
get nonIpUrls() {
|
||||
return unique(addresses.flatMap((x) => x.nonIpUrls))
|
||||
},
|
||||
get allUrls() {
|
||||
return unique(addresses.flatMap((x) => x.allUrls))
|
||||
},
|
||||
}
|
||||
}
|
||||
const makeInterfaceFilled = async ({
|
||||
effects,
|
||||
interfaceId,
|
||||
packageId,
|
||||
callback,
|
||||
}: {
|
||||
effects: Effects
|
||||
interfaceId: string
|
||||
packageId: string | undefined
|
||||
callback: () => void
|
||||
}) => {
|
||||
const interfaceValue = await effects.getInterface({
|
||||
interfaceId,
|
||||
packageId,
|
||||
callback,
|
||||
})
|
||||
const hostIdsRecord: { [hostId: HostId]: HostName[] } = Object.fromEntries(
|
||||
await Promise.all(
|
||||
unique(interfaceValue.addresses.map((x) => x.hostId)).map(
|
||||
async (hostId) => [
|
||||
hostId,
|
||||
effects.getHostnames({
|
||||
packageId,
|
||||
hostId,
|
||||
callback,
|
||||
}),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
const fillAddress = filledAddress.bind(null, hostIdsRecord)
|
||||
const interfaceFilled: NetworkInterfaceFilled = networkInterfaceFilled(
|
||||
interfaceValue,
|
||||
interfaceValue.addresses.map(fillAddress),
|
||||
)
|
||||
return interfaceFilled
|
||||
}
|
||||
|
||||
export class GetNetworkInterface {
|
||||
constructor(
|
||||
readonly effects: Effects,
|
||||
readonly opts: { interfaceId: string; packageId?: string },
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Returns the value of Store at the provided path. Restart the service if the value changes
|
||||
*/
|
||||
async const() {
|
||||
const { interfaceId, packageId } = this.opts
|
||||
const callback = this.effects.restart
|
||||
const interfaceFilled: NetworkInterfaceFilled = await makeInterfaceFilled({
|
||||
effects: this.effects,
|
||||
interfaceId,
|
||||
packageId,
|
||||
callback,
|
||||
})
|
||||
|
||||
return interfaceFilled
|
||||
}
|
||||
/**
|
||||
* Returns the value of NetworkInterfacesFilled at the provided path. Does nothing if the value changes
|
||||
*/
|
||||
async once() {
|
||||
const { interfaceId, packageId } = this.opts
|
||||
const callback = () => {}
|
||||
const interfaceFilled: NetworkInterfaceFilled = await makeInterfaceFilled({
|
||||
effects: this.effects,
|
||||
interfaceId,
|
||||
packageId,
|
||||
callback,
|
||||
})
|
||||
|
||||
return interfaceFilled
|
||||
}
|
||||
|
||||
/**
|
||||
* Watches the value of NetworkInterfacesFilled at the provided path. Takes a custom callback function to run whenever the value changes
|
||||
*/
|
||||
async *watch() {
|
||||
const { interfaceId, packageId } = this.opts
|
||||
while (true) {
|
||||
let callback: () => void = () => {}
|
||||
const waitForNext = new Promise<void>((resolve) => {
|
||||
callback = resolve
|
||||
})
|
||||
yield await makeInterfaceFilled({
|
||||
effects: this.effects,
|
||||
interfaceId,
|
||||
packageId,
|
||||
callback,
|
||||
})
|
||||
await waitForNext
|
||||
}
|
||||
}
|
||||
}
|
||||
export function getNetworkInterface(
|
||||
effects: Effects,
|
||||
opts: { interfaceId: string; packageId?: string },
|
||||
) {
|
||||
return new GetNetworkInterface(effects, opts)
|
||||
}
|
||||
112
lib/util/getNetworkInterfaces.ts
Normal file
112
lib/util/getNetworkInterfaces.ts
Normal file
@@ -0,0 +1,112 @@
|
||||
import { Address, Effects, EnsureStorePath, HostName, hostName } from "../types"
|
||||
import * as regexes from "./regexes"
|
||||
import {
|
||||
HostId,
|
||||
NetworkInterfaceFilled,
|
||||
filledAddress,
|
||||
networkInterfaceFilled,
|
||||
} from "./getNetworkInterface"
|
||||
|
||||
const makeManyInterfaceFilled = async ({
|
||||
effects,
|
||||
packageId,
|
||||
callback,
|
||||
}: {
|
||||
effects: Effects
|
||||
packageId: string | undefined
|
||||
callback: () => void
|
||||
}) => {
|
||||
const interfaceValues = await effects.listInterface({
|
||||
packageId,
|
||||
callback,
|
||||
})
|
||||
const hostIdsRecord: { [hostId: HostId]: HostName[] } = Object.fromEntries(
|
||||
await Promise.all(
|
||||
Array.from(
|
||||
new Set(
|
||||
interfaceValues.flatMap((x) => x.addresses).map((x) => x.hostId),
|
||||
),
|
||||
).map(async (hostId) => [
|
||||
hostId,
|
||||
effects.getHostnames({
|
||||
packageId,
|
||||
hostId,
|
||||
callback,
|
||||
}),
|
||||
]),
|
||||
),
|
||||
)
|
||||
const fillAddress = filledAddress.bind(null, hostIdsRecord)
|
||||
|
||||
const interfacesFilled: NetworkInterfaceFilled[] = interfaceValues.map(
|
||||
(interfaceValue) =>
|
||||
networkInterfaceFilled(
|
||||
interfaceValue,
|
||||
interfaceValue.addresses.map(fillAddress),
|
||||
),
|
||||
)
|
||||
return interfacesFilled
|
||||
}
|
||||
|
||||
export class GetNetworkInterfaces {
|
||||
constructor(
|
||||
readonly effects: Effects,
|
||||
readonly opts: { packageId?: string },
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Returns the value of Store at the provided path. Restart the service if the value changes
|
||||
*/
|
||||
async const() {
|
||||
const { packageId } = this.opts
|
||||
const callback = this.effects.restart
|
||||
const interfaceFilled: NetworkInterfaceFilled[] =
|
||||
await makeManyInterfaceFilled({
|
||||
effects: this.effects,
|
||||
packageId,
|
||||
callback,
|
||||
})
|
||||
|
||||
return interfaceFilled
|
||||
}
|
||||
/**
|
||||
* Returns the value of NetworkInterfacesFilled at the provided path. Does nothing if the value changes
|
||||
*/
|
||||
async once() {
|
||||
const { packageId } = this.opts
|
||||
const callback = () => {}
|
||||
const interfaceFilled: NetworkInterfaceFilled[] =
|
||||
await makeManyInterfaceFilled({
|
||||
effects: this.effects,
|
||||
packageId,
|
||||
callback,
|
||||
})
|
||||
|
||||
return interfaceFilled
|
||||
}
|
||||
|
||||
/**
|
||||
* Watches the value of NetworkInterfacesFilled at the provided path. Takes a custom callback function to run whenever the value changes
|
||||
*/
|
||||
async *watch() {
|
||||
const { packageId } = this.opts
|
||||
while (true) {
|
||||
let callback: () => void = () => {}
|
||||
const waitForNext = new Promise<void>((resolve) => {
|
||||
callback = resolve
|
||||
})
|
||||
yield await makeManyInterfaceFilled({
|
||||
effects: this.effects,
|
||||
packageId,
|
||||
callback,
|
||||
})
|
||||
await waitForNext
|
||||
}
|
||||
}
|
||||
}
|
||||
export function getNetworkInterfaces(
|
||||
effects: Effects,
|
||||
opts: { packageId?: string },
|
||||
) {
|
||||
return new GetNetworkInterfaces(effects, opts)
|
||||
}
|
||||
@@ -13,9 +13,12 @@ export const url =
|
||||
export const local =
|
||||
/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.local\b([-a-zA-Z0-9()!@:%_\+.~#?&\/\/=]*)/
|
||||
|
||||
export const localHost = /[-a-zA-Z0-9@:%._\+~#=]{1,256}\.local/
|
||||
|
||||
export const onion =
|
||||
/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.onion\b([-a-zA-Z0-9()!@:%_\+.~#?&\/\/=]*)/
|
||||
|
||||
export const onionHost = /[-a-zA-Z0-9@:%._\+~#=]{1,256}\.onion/
|
||||
// https://ihateregex.io/expr/ascii/
|
||||
export const ascii = /^[ -~]*$/
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import * as T from "../types"
|
||||
import FileHelper from "./fileHelper"
|
||||
import nullIfEmpty from "./nullIfEmpty"
|
||||
import {
|
||||
@@ -6,7 +5,13 @@ import {
|
||||
checkPortListening,
|
||||
checkWebUrl,
|
||||
} from "../health/checkFns"
|
||||
import { ExtractStore } from "../types"
|
||||
import {
|
||||
Effects,
|
||||
EnsureStorePath,
|
||||
ExtractStore,
|
||||
InterfaceId,
|
||||
PackageId,
|
||||
} from "../types"
|
||||
import { GetSystemSmtp } from "./GetSystemSmtp"
|
||||
import { DefaultString } from "../config/configTypes"
|
||||
import { getDefaultString } from "./getDefaultString"
|
||||
@@ -24,6 +29,11 @@ import {
|
||||
} from "../dependency/setupDependencyMounts"
|
||||
import { Host, MultiHost, SingleHost, StaticHost } from "../interfaces/Host"
|
||||
import { NetworkInterfaceBuilder } from "../interfaces/NetworkInterfaceBuilder"
|
||||
import { GetNetworkInterface, getNetworkInterface } from "./getNetworkInterface"
|
||||
import {
|
||||
GetNetworkInterfaces,
|
||||
getNetworkInterfaces,
|
||||
} from "./getNetworkInterfaces"
|
||||
|
||||
export type Utils<Store, Vault, WrapperOverWrite = { const: never }> = {
|
||||
checkPortListening(
|
||||
@@ -73,18 +83,29 @@ export type Utils<Store, Vault, WrapperOverWrite = { const: never }> = {
|
||||
>(
|
||||
value: In,
|
||||
) => Promise<MountDependenciesOut<In>>
|
||||
networkInterface: {
|
||||
getOwn: (interfaceId: InterfaceId) => GetNetworkInterface & WrapperOverWrite
|
||||
get: (opts: {
|
||||
interfaceId: InterfaceId
|
||||
packageId: PackageId
|
||||
}) => GetNetworkInterface & WrapperOverWrite
|
||||
getAllOwn: () => GetNetworkInterfaces & WrapperOverWrite
|
||||
getAll: (opts: {
|
||||
packageId: PackageId
|
||||
}) => GetNetworkInterfaces & WrapperOverWrite
|
||||
}
|
||||
nullIfEmpty: typeof nullIfEmpty
|
||||
readFile: <A>(fileHelper: FileHelper<A>) => ReturnType<FileHelper<A>["read"]>
|
||||
store: {
|
||||
get: <Path extends string>(
|
||||
packageId: string,
|
||||
path: T.EnsureStorePath<Store, Path>,
|
||||
path: EnsureStorePath<Store, Path>,
|
||||
) => GetStore<Store, Path> & WrapperOverWrite
|
||||
getOwn: <Path extends string>(
|
||||
path: T.EnsureStorePath<Store, Path>,
|
||||
path: EnsureStorePath<Store, Path>,
|
||||
) => GetStore<Store, Path> & WrapperOverWrite
|
||||
setOwn: <Path extends string | never>(
|
||||
path: T.EnsureStorePath<Store, Path>,
|
||||
path: EnsureStorePath<Store, Path>,
|
||||
value: ExtractStore<Store, Path>,
|
||||
) => Promise<void>
|
||||
}
|
||||
@@ -102,7 +123,7 @@ export const utils = <
|
||||
Vault = never,
|
||||
WrapperOverWrite = { const: never },
|
||||
>(
|
||||
effects: T.Effects,
|
||||
effects: Effects,
|
||||
): Utils<Store, Vault, WrapperOverWrite> => ({
|
||||
createOrUpdateVault: async ({
|
||||
key,
|
||||
@@ -147,18 +168,33 @@ export const utils = <
|
||||
writeFile: <A>(fileHelper: FileHelper<A>, data: A) =>
|
||||
fileHelper.write(data, effects),
|
||||
nullIfEmpty,
|
||||
|
||||
networkInterface: {
|
||||
getOwn: (interfaceId: InterfaceId) =>
|
||||
getNetworkInterface(effects, { interfaceId }) as GetNetworkInterface &
|
||||
WrapperOverWrite,
|
||||
get: (opts: { interfaceId: InterfaceId; packageId: PackageId }) =>
|
||||
getNetworkInterface(effects, opts) as GetNetworkInterface &
|
||||
WrapperOverWrite,
|
||||
getAllOwn: () =>
|
||||
getNetworkInterfaces(effects, {}) as GetNetworkInterfaces &
|
||||
WrapperOverWrite,
|
||||
getAll: (opts: { packageId: PackageId }) =>
|
||||
getNetworkInterfaces(effects, opts) as GetNetworkInterfaces &
|
||||
WrapperOverWrite,
|
||||
},
|
||||
store: {
|
||||
get: <Path extends string = never>(
|
||||
packageId: string,
|
||||
path: T.EnsureStorePath<Store, Path>,
|
||||
path: EnsureStorePath<Store, Path>,
|
||||
) =>
|
||||
getStore<Store, Path>(effects, path as any, {
|
||||
packageId,
|
||||
}) as any,
|
||||
getOwn: <Path extends string>(path: T.EnsureStorePath<Store, Path>) =>
|
||||
getOwn: <Path extends string>(path: EnsureStorePath<Store, Path>) =>
|
||||
getStore<Store, Path>(effects, path as any) as any,
|
||||
setOwn: <Path extends string | never>(
|
||||
path: T.EnsureStorePath<Store, Path>,
|
||||
path: EnsureStorePath<Store, Path>,
|
||||
value: ExtractStore<Store, Path>,
|
||||
) => effects.store.set<Store, Path>({ value, path: path as any }),
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user