chore: Add in some more files for the testing of the sdk and the rust interface

This commit is contained in:
J H
2024-03-13 16:23:24 -06:00
parent ba325b1581
commit b6fe0be1b2
46 changed files with 451 additions and 116 deletions

View File

@@ -60,6 +60,6 @@ function asMessage(e: unknown) {
if (typeof e === "object" && e != null && "message" in e)
return String(e.message)
const value = String(e)
if (value.length == null) return undefined
if (value.length == null) return null
return value
}

View File

@@ -2,5 +2,5 @@ import { HealthStatus } from "../../types"
export type CheckResult = {
status: HealthStatus
message?: string
message: string | null
}

View File

@@ -57,7 +57,7 @@ export type Scheme = string | null
type AddSslOptions = {
scheme: Scheme
preferredExternalPort: number
addXForwardedHeaders?: boolean /** default: false */
addXForwardedHeaders: boolean | null /** default: false */
}
type Security = { secure: false; ssl: false } | { secure: true; ssl: boolean }
export type BindOptions = {
@@ -82,13 +82,13 @@ type BindOptionsByKnownProtocol =
| ({
protocol: ProtocolsWithSslVariants
preferredExternalPort?: number
scheme?: Scheme
scheme: Scheme | null
} & ({ noAddSsl: true } | { addSsl?: Partial<AddSslOptions> }))
| {
protocol: NotProtocolsWithSslVariants
preferredExternalPort?: number
scheme?: Scheme
addSsl?: AddSslOptions | null
scheme: Scheme | null
addSsl: AddSslOptions | null
}
type BindOptionsByProtocol = BindOptionsByKnownProtocol | BindOptions
@@ -185,6 +185,7 @@ export class Host {
if ("noAddSsl" in options && options.noAddSsl) return null
if ("withSsl" in protoInfo && protoInfo.withSsl)
return {
addXForwardedHeaders: null,
preferredExternalPort: knownProtocols[protoInfo.withSsl].defaultPort,
scheme: protoInfo.withSsl,
...("addSsl" in options ? options.addSsl : null),

View File

@@ -7,7 +7,10 @@ describe("host", () => {
async function test(effects: Effects) {
const utils = createUtils<never, never>(effects)
const foo = utils.host.multi("foo")
const fooOrigin = await foo.bindPort(80, { protocol: "http" as const })
const fooOrigin = await foo.bindPort(80, {
protocol: "http" as const,
scheme: null,
})
const fooInterface = new ServiceInterfaceBuilder({
effects,
name: "Foo",

View File

@@ -0,0 +1,75 @@
import { Effects } from "../types"
import { ExecuteAction } from "../../../core/startos/bindings/ExecuteAction"
import { CreateOverlayedImageParams } from "../../../core/startos/bindings/CreateOverlayedImageParams"
import { DestroyOverlayedImageParams } from "../../../core/startos/bindings/DestroyOverlayedImageParams"
import { BindParams } from "../../../core/startos/bindings/BindParams"
import { GetHostInfoParams } from "../../../core/startos/bindings/GetHostInfoParams"
import { ParamsPackageId } from "../../../core/startos/bindings/ParamsPackageId"
import { ParamsMaybePackageId } from "../../../core/startos/bindings/ParamsMaybePackageId"
import { SetConfigured } from "../../../core/startos/bindings/SetConfigured"
import { SetHealth } from "../../../core/startos/bindings/SetHealth"
import { ExposeForDependentsParams } from "../../../core/startos/bindings/ExposeForDependentsParams"
import { ExposeUiParams } from "../../../core/startos/bindings/ExposeUiParams"
import { GetSslCertificateParams } from "../../../core/startos/bindings/GetSslCertificateParams"
import { GetSslKeyParams } from "../../../core/startos/bindings/GetSslKeyParams"
import { GetServiceInterfaceParams } from "../../../core/startos/bindings/GetServiceInterfaceParams"
function typeEquality<ExpectedType>(_a: ExpectedType) {}
describe("startosTypeValidation ", () => {
test(`checking the params match`, () => {
const testInput: any = {}
typeEquality<{
[K in keyof Effects &
(
| "gitInfo"
| "echo"
| "chroot"
| "exists"
| "executeAction"
| "getConfigured"
| "stopped"
| "running"
| "restart"
| "shutdown"
| "setConfigured"
| "setMainStatus"
| "setHealth"
| "getStore"
| "setStore"
| "exposeForDependents"
| "exposeUi"
| "createOverlayedImage"
| "destroyOverlayedImage"
| "getSslCertificate"
| "getSslKey"
| "getServiceInterface"
| "clearBindings"
| "bind"
| "getHostInfo"
)]: Effects[K] extends Function ? Parameters<Effects[K]>[0] : never
}>({
executeAction: {} as ExecuteAction,
createOverlayedImage: {} as CreateOverlayedImageParams,
destroyOverlayedImage: {} as DestroyOverlayedImageParams,
clearBindings: undefined,
bind: {} as BindParams,
getHostInfo: {} as GetHostInfoParams,
exists: {} as ParamsPackageId,
getConfigured: undefined,
stopped: {} as ParamsMaybePackageId,
running: {} as ParamsMaybePackageId,
restart: undefined,
shutdown: undefined,
setConfigured: {} as SetConfigured,
setHealth: {} as SetHealth,
exposeForDependents: {} as ExposeForDependentsParams,
exposeUi: {} as ExposeUiParams,
getSslCertificate: {} as GetSslCertificateParams,
getSslKey: {} as GetSslKeyParams,
getServiceInterface: {} as GetServiceInterfaceParams,
})
typeEquality<Parameters<Effects["executeAction"]>[0]>(
testInput as ExecuteAction,
)
})
})

View File

@@ -1,7 +1,8 @@
export * as configTypes from "./config/configTypes"
import { AddSslOptions } from "../../core/startos/bindings/AddSslOptions"
import { InputSpec } from "./config/configTypes"
import { DependenciesReceipt } from "./config/setupConfig"
import { BindOptions } from "./interfaces/Host"
import { BindOptions, Scheme } from "./interfaces/Host"
import { Daemons } from "./mainFn/Daemons"
import { UrlString } from "./util/getServiceInterface"
import { ServiceInterfaceType, Signals } from "./util/utils"
@@ -247,6 +248,7 @@ export type ServiceInterfaceWithHostInfo = ServiceInterface & {
// prettier-ignore
export type ExposeAllServicePaths<Store, PreviousPath extends string = ""> =
Store extends never ? string :
Store extends Record<string, unknown> ? {[K in keyof Store & string]: ExposeAllServicePaths<Store[K], `${PreviousPath}/${K & string}`>}[keyof Store & string] :
PreviousPath
// prettier-ignore
@@ -254,10 +256,10 @@ export type ExposeAllUiPaths<Store, PreviousPath extends string = ""> =
Store extends Record<string, unknown> ? {[K in keyof Store & string]: ExposeAllUiPaths<Store[K], `${PreviousPath}/${K & string}`>}[keyof Store & string] :
Store extends string ? PreviousPath :
never
export type ExposeServicePaths<Store> = Array<{
export type ExposeServicePaths<Store = never> = {
/** The path to the value in the Store. [JsonPath](https://jsonpath.com/) */
path: ExposeAllServicePaths<Store>
}>
paths: Store extends never ? string[] : ExposeAllServicePaths<Store>[]
}
export type ExposeUiPaths<Store> = Array<{
/** The path to the value in the Store. [JsonPath](https://jsonpath.com/) */
@@ -292,24 +294,28 @@ export type Effects = {
/** Removes all network bindings */
clearBindings(): Promise<void>
/** Creates a host connected to the specified port with the provided options */
bind(
options: {
kind: "static" | "single" | "multi"
id: string
internalPort: number
} & BindOptions,
): Promise<void>
bind(options: {
kind: "static" | "single" | "multi"
id: string
internalPort: number
scheme: Scheme
preferredExternalPort: number
addSsl: AddSslOptions | null
secure: boolean
ssl: boolean
}): Promise<void>
/** Retrieves the current hostname(s) associated with a host id */
// getHostInfo(options: {
// kind: "static" | "single"
// serviceInterfaceId: string
// packageId: string | null
// callback: () => void
// }): Promise<SingleHost>
getHostInfo(options: {
kind: "static" | "single"
kind: "multi" | null
serviceInterfaceId: string
packageId?: string
callback: () => void
}): Promise<SingleHost>
getHostInfo(options: {
kind?: "multi"
serviceInterfaceId: string
packageId?: string
packageId: string | null
callback: () => void
}): Promise<MultiHost>
@@ -368,12 +374,17 @@ export type Effects = {
*/
exportServiceInterface(options: ServiceInterface): Promise<string>
exposeForDependents<Store = never>(
options: ExposeServicePaths<Store>,
): Promise<void>
exposeForDependents(options: { paths: string[] }): Promise<void>
exposeUi<Store = never>(options: {
paths: ExposeUiPaths<Store>
paths: {
path: string
title: string
description?: string | undefined
masked?: boolean | undefined
copyable?: boolean | undefined
qr?: boolean | undefined
}[]
}): Promise<void>
/**
* There are times that we want to see the addresses that where exported
@@ -382,7 +393,7 @@ export type Effects = {
* Note: any auth should be filtered out already
*/
getServiceInterface(options: {
packageId?: PackageId
packageId: PackageId | null
serviceInterfaceId: ServiceInterfaceId
callback: () => void
}): Promise<ServiceInterface>
@@ -392,7 +403,7 @@ export type Effects = {
* @param options
*/
getPrimaryUrl(options: {
packageId?: PackageId
packageId: PackageId | null
serviceInterfaceId: ServiceInterfaceId
callback: () => void
}): Promise<UrlString | null>
@@ -404,7 +415,7 @@ export type Effects = {
* Note: any auth should be filtered out already
*/
listServiceInterfaces(options: {
packageId?: PackageId
packageId: PackageId | null
callback: () => void
}): Promise<ServiceInterface[]>
@@ -429,38 +440,38 @@ export type Effects = {
* This called after a valid set config as well as during init.
* @param configured
*/
setConfigured(configured: boolean): Promise<void>
setConfigured(options: { configured: boolean }): Promise<void>
/**
*
* @returns PEM encoded fullchain (ecdsa)
*/
getSslCertificate: (
packageId: string | null,
hostId: string,
algorithm?: "ecdsa" | "ed25519",
) => Promise<[string, string, string]>
getSslCertificate: (options: {
packageId: string | null
hostId: string
algorithm: "ecdsa" | "ed25519" | null
}) => Promise<[string, string, string]>
/**
* @returns PEM encoded ssl key (ecdsa)
*/
getSslKey: (
packageId: string | null,
hostId: string,
algorithm?: "ecdsa" | "ed25519",
) => Promise<string>
getSslKey: (options: {
packageId: string | null
hostId: string
algorithm: "ecdsa" | "ed25519" | null
}) => Promise<string>
setHealth(o: {
name: string
status: HealthStatus
message?: string
message: string | null
}): Promise<void>
/** Set the dependencies of what the service needs, usually ran during the set config as a best practice */
setDependencies(dependencies: Dependencies): Promise<DependenciesReceipt>
/** Exists could be useful during the runtime to know if some service exists, option dep */
exists(packageId: PackageId): Promise<boolean>
exists(options: { packageId: PackageId }): Promise<boolean>
/** Exists could be useful during the runtime to know if some service is running, option dep */
running(packageId: PackageId): Promise<boolean>
running(options: { packageId: PackageId }): Promise<boolean>
/** Instead of creating proxies with nginx, we have a utility to create and maintain a proxy in the lifetime of this running. */
reverseProxy(options: {
@@ -494,7 +505,7 @@ export type Effects = {
}
}): Promise<string>
stopped(packageId?: string): Promise<boolean>
stopped(options: { packageId: string | null }): Promise<boolean>
}
// prettier-ignore

View File

@@ -185,7 +185,7 @@ const makeInterfaceFilled = async ({
}: {
effects: Effects
id: string
packageId: string | undefined
packageId: string | null
callback: () => void
}) => {
const serviceInterfaceValue = await effects.getServiceInterface({
@@ -195,6 +195,7 @@ const makeInterfaceFilled = async ({
})
const hostInfo = await effects.getHostInfo({
packageId,
kind: null,
serviceInterfaceId: serviceInterfaceValue.id,
callback,
})
@@ -220,7 +221,7 @@ const makeInterfaceFilled = async ({
export class GetServiceInterface {
constructor(
readonly effects: Effects,
readonly opts: { id: string; packageId?: string },
readonly opts: { id: string; packageId: string | null },
) {}
/**
@@ -276,7 +277,7 @@ export class GetServiceInterface {
}
export function getServiceInterface(
effects: Effects,
opts: { id: string; packageId?: string },
opts: { id: string; packageId: string | null },
) {
return new GetServiceInterface(effects, opts)
}

View File

@@ -11,7 +11,7 @@ const makeManyInterfaceFilled = async ({
callback,
}: {
effects: Effects
packageId: string | undefined
packageId: string | null
callback: () => void
}) => {
const serviceInterfaceValues = await effects.listServiceInterfaces({
@@ -25,6 +25,7 @@ const makeManyInterfaceFilled = async ({
[
id,
await effects.getHostInfo({
kind: null,
packageId,
serviceInterfaceId: id,
callback,
@@ -37,6 +38,7 @@ const makeManyInterfaceFilled = async ({
const serviceInterfacesFilled: ServiceInterfaceFilled[] = await Promise.all(
serviceInterfaceValues.map(async (serviceInterfaceValue) => {
const hostInfo = await effects.getHostInfo({
kind: null,
packageId,
serviceInterfaceId: serviceInterfaceValue.id,
callback,
@@ -64,7 +66,7 @@ const makeManyInterfaceFilled = async ({
export class GetServiceInterfaces {
constructor(
readonly effects: Effects,
readonly opts: { packageId?: string },
readonly opts: { packageId: string | null },
) {}
/**
@@ -119,7 +121,7 @@ export class GetServiceInterfaces {
}
export function getServiceInterfaces(
effects: Effects,
opts: { packageId?: string },
opts: { packageId: string | null },
) {
return new GetServiceInterfaces(effects, opts)
}

View File

@@ -177,14 +177,17 @@ export const createUtils = <
serviceInterface: {
getOwn: (id: ServiceInterfaceId) =>
getServiceInterface(effects, { id }) as GetServiceInterface &
WrapperOverWrite,
getServiceInterface(effects, {
id,
packageId: null,
}) as GetServiceInterface & WrapperOverWrite,
get: (opts: { id: ServiceInterfaceId; packageId: PackageId }) =>
getServiceInterface(effects, opts) as GetServiceInterface &
WrapperOverWrite,
getAllOwn: () =>
getServiceInterfaces(effects, {}) as GetServiceInterfaces &
WrapperOverWrite,
getServiceInterfaces(effects, {
packageId: null,
}) as GetServiceInterfaces & WrapperOverWrite,
getAll: (opts: { packageId: PackageId }) =>
getServiceInterfaces(effects, opts) as GetServiceInterfaces &
WrapperOverWrite,