mirror of
https://github.com/Start9Labs/start-sdk.git
synced 2026-03-26 02:11:56 +00:00
fixes from testing
This commit is contained in:
@@ -14,6 +14,7 @@ export type ValueType =
|
||||
| "union"
|
||||
export type ValueSpec = ValueSpecOf<ValueType>
|
||||
/** core spec types. These types provide the metadata for performing validations */
|
||||
// prettier-ignore
|
||||
export type ValueSpecOf<T extends ValueType> = T extends "text"
|
||||
? ValueSpecText
|
||||
: T extends "textarea"
|
||||
@@ -164,10 +165,10 @@ export type ListValueSpecType = "text" | "number" | "object"
|
||||
export type ListValueSpecOf<T extends ListValueSpecType> = T extends "text"
|
||||
? ListValueSpecText
|
||||
: T extends "number"
|
||||
? ListValueSpecNumber
|
||||
: T extends "object"
|
||||
? ListValueSpecObject
|
||||
: never
|
||||
? ListValueSpecNumber
|
||||
: T extends "object"
|
||||
? ListValueSpecObject
|
||||
: never
|
||||
/** represents a spec for a list */
|
||||
export type ValueSpecList = ValueSpecListOf<ListValueSpecType>
|
||||
export interface ValueSpecListOf<T extends ListValueSpecType>
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Effects, ExpectedExports } from "../types"
|
||||
import { SDKManifest } from "../manifest/ManifestTypes"
|
||||
import * as D from "./configDependencies"
|
||||
import { Config, ExtractConfigType } from "./builder/config"
|
||||
import { Utils, utils } from "../util/utils"
|
||||
import { Utils, createUtils } from "../util/utils"
|
||||
import nullIfEmpty from "../util/nullIfEmpty"
|
||||
import { InterfaceReceipt } from "../interfaces/interfaceReceipt"
|
||||
import { InterfacesReceipt as InterfacesReceipt } from "../interfaces/setupInterfaces"
|
||||
@@ -72,7 +72,7 @@ export function setupConfig<
|
||||
const { restart } = await write({
|
||||
input: JSON.parse(JSON.stringify(input)),
|
||||
effects,
|
||||
utils: utils(effects),
|
||||
utils: createUtils(effects),
|
||||
dependencies: D.configDependenciesSet<Manifest>(),
|
||||
})
|
||||
if (restart) {
|
||||
@@ -80,7 +80,7 @@ export function setupConfig<
|
||||
}
|
||||
}) as ExpectedExports.setConfig,
|
||||
getConfig: (async ({ effects }) => {
|
||||
const myUtils = utils<Manifest, Store>(effects)
|
||||
const myUtils = createUtils<Manifest, Store>(effects)
|
||||
const configValue = nullIfEmpty(
|
||||
(await read({ effects, utils: myUtils })) || null,
|
||||
)
|
||||
|
||||
@@ -3,7 +3,7 @@ import {
|
||||
DeepPartial,
|
||||
Effects,
|
||||
} from "../types"
|
||||
import { Utils, utils } from "../util/utils"
|
||||
import { Utils, createUtils } from "../util/utils"
|
||||
import { deepEqual } from "../util/deepEqual"
|
||||
import { deepMerge } from "../util/deepMerge"
|
||||
import { SDKManifest } from "../manifest/ManifestTypes"
|
||||
@@ -41,7 +41,7 @@ export class DependencyConfig<
|
||||
return this.dependencyConfig({
|
||||
localConfig: options.localConfig as Input,
|
||||
effects: options.effects,
|
||||
utils: utils<Manifest, Store>(options.effects),
|
||||
utils: createUtils<Manifest, Store>(options.effects),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { SDKManifest } from "../manifest/ManifestTypes"
|
||||
import { Effects, ExpectedExports } from "../types"
|
||||
import { Utils, utils } from "../util/utils"
|
||||
import { Utils, createUtils } from "../util/utils"
|
||||
|
||||
export type InstallFn<Manifest extends SDKManifest, Store> = (opts: {
|
||||
effects: Effects
|
||||
@@ -21,7 +21,7 @@ export class Install<Manifest extends SDKManifest, Store> {
|
||||
if (!previousVersion)
|
||||
await this.fn({
|
||||
effects,
|
||||
utils: utils(effects),
|
||||
utils: createUtils(effects),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { SDKManifest } from "../manifest/ManifestTypes"
|
||||
import { Effects, ExpectedExports } from "../types"
|
||||
import { Utils, utils } from "../util/utils"
|
||||
import { Utils, createUtils } from "../util/utils"
|
||||
|
||||
export type UninstallFn<Manifest extends SDKManifest, Store> = (opts: {
|
||||
effects: Effects
|
||||
@@ -21,7 +21,7 @@ export class Uninstall<Manifest extends SDKManifest, Store> {
|
||||
if (!nextVersion)
|
||||
await this.fn({
|
||||
effects,
|
||||
utils: utils(effects),
|
||||
utils: createUtils(effects),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,10 +2,7 @@ import { Address } from "../types"
|
||||
import { Host, PortOptions } from "./Host"
|
||||
|
||||
export class Origin<T extends Host> {
|
||||
constructor(
|
||||
readonly host: T,
|
||||
readonly options: PortOptions,
|
||||
) {}
|
||||
constructor(readonly host: T, readonly options: PortOptions) {}
|
||||
|
||||
build({ username, path, search }: BuildOptions): Address {
|
||||
const qpEntries = Object.entries(search)
|
||||
|
||||
@@ -52,7 +52,7 @@ Daemons.of({
|
||||
export class Daemons<Manifest extends SDKManifest, Ids extends string> {
|
||||
private constructor(
|
||||
readonly effects: Effects,
|
||||
readonly started: (onTerm: () => void) => null,
|
||||
readonly started: (onTerm: () => PromiseLike<void>) => PromiseLike<void>,
|
||||
readonly daemons?: Daemon<Manifest, Ids, "command", Ids>[],
|
||||
) {}
|
||||
/**
|
||||
@@ -67,7 +67,7 @@ export class Daemons<Manifest extends SDKManifest, Ids extends string> {
|
||||
*/
|
||||
static of<Manifest extends SDKManifest>(config: {
|
||||
effects: Effects
|
||||
started: (onTerm: () => void) => null
|
||||
started: (onTerm: () => PromiseLike<void>) => PromiseLike<void>
|
||||
healthReceipts: HealthReceipt[]
|
||||
}) {
|
||||
return new Daemons<Manifest, never>(config.effects, config.started)
|
||||
@@ -123,7 +123,7 @@ export class Daemons<Manifest extends SDKManifest, Ids extends string> {
|
||||
({
|
||||
status: "failing",
|
||||
message: "message" in err ? err.message : String(err),
|
||||
}) as CheckResult,
|
||||
} as CheckResult),
|
||||
)
|
||||
currentInput.lastResult = response.status || null
|
||||
if (!currentInput.hadSuccess && response.status === "passing") {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Effects, ExpectedExports } from "../types"
|
||||
import { createMainUtils } from "../util"
|
||||
import { Utils, utils } from "../util/utils"
|
||||
import { Utils, createUtils } from "../util/utils"
|
||||
import { Daemons } from "./Daemons"
|
||||
import "../interfaces/NetworkInterfaceBuilder"
|
||||
import "../interfaces/Origin"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Effects } from "../types"
|
||||
import { createMainUtils } from "../util"
|
||||
import { utils } from "../util/utils"
|
||||
import { createUtils } from "../util/utils"
|
||||
|
||||
type Store = {
|
||||
config: {
|
||||
@@ -15,23 +15,23 @@ const noop = () => {}
|
||||
describe("Store", () => {
|
||||
test("types", async () => {
|
||||
;async () => {
|
||||
utils<Manifest, Store>(todo<Effects>()).store.setOwn("/config", {
|
||||
createUtils<Manifest, Store>(todo<Effects>()).store.setOwn("/config", {
|
||||
someValue: "a",
|
||||
})
|
||||
utils<Manifest, Store>(todo<Effects>()).store.setOwn(
|
||||
createUtils<Manifest, Store>(todo<Effects>()).store.setOwn(
|
||||
"/config/someValue",
|
||||
"b",
|
||||
)
|
||||
utils<Manifest, Store>(todo<Effects>()).store.setOwn("", {
|
||||
createUtils<Manifest, Store>(todo<Effects>()).store.setOwn("", {
|
||||
config: { someValue: "b" },
|
||||
})
|
||||
utils<Manifest, Store>(todo<Effects>()).store.setOwn(
|
||||
createUtils<Manifest, Store>(todo<Effects>()).store.setOwn(
|
||||
"/config/someValue",
|
||||
|
||||
// @ts-expect-error Type is wrong for the setting value
|
||||
5,
|
||||
)
|
||||
utils(todo<Effects>()).store.setOwn(
|
||||
createUtils(todo<Effects>()).store.setOwn(
|
||||
// @ts-expect-error Path is wrong
|
||||
"/config/someVae3lue",
|
||||
"someValue",
|
||||
@@ -64,31 +64,31 @@ describe("Store", () => {
|
||||
.const()
|
||||
/// ----------------- ERRORS -----------------
|
||||
|
||||
utils<Manifest, Store>(todo<Effects>()).store.setOwn("", {
|
||||
createUtils<Manifest, Store>(todo<Effects>()).store.setOwn("", {
|
||||
// @ts-expect-error Type is wrong for the setting value
|
||||
config: { someValue: "notInAOrB" },
|
||||
})
|
||||
utils<Manifest, Store>(todo<Effects>()).store.setOwn(
|
||||
createUtils<Manifest, Store>(todo<Effects>()).store.setOwn(
|
||||
"/config/someValue",
|
||||
// @ts-expect-error Type is wrong for the setting value
|
||||
"notInAOrB",
|
||||
)
|
||||
;(await utils<Manifest, Store>(todo<Effects>())
|
||||
;(await createUtils<Manifest, Store>(todo<Effects>())
|
||||
.store.getOwn("/config/someValue")
|
||||
// @ts-expect-error Const should normally not be callable
|
||||
.const()) satisfies string
|
||||
;(await utils<Manifest, Store>(todo<Effects>())
|
||||
;(await createUtils<Manifest, Store>(todo<Effects>())
|
||||
.store.getOwn("/config")
|
||||
// @ts-expect-error Const should normally not be callable
|
||||
.const()) satisfies Store["config"]
|
||||
await utils<Manifest, Store>(todo<Effects>())
|
||||
await createUtils<Manifest, Store>(todo<Effects>())
|
||||
// @ts-expect-error Path is wrong
|
||||
.store.getOwn("/config/somdsfeValue")
|
||||
// @ts-expect-error Const should normally not be callable
|
||||
.const()
|
||||
|
||||
///
|
||||
;(await utils<Manifest, Store>(todo<Effects>())
|
||||
;(await createUtils<Manifest, Store>(todo<Effects>())
|
||||
.store.getOwn("/config/someValue")
|
||||
// @ts-expect-error satisfies type is wrong
|
||||
.const()) satisfies number
|
||||
|
||||
@@ -114,8 +114,8 @@ export type ValidIfNoStupidEscape<A> = A extends
|
||||
| `${string}\\"${string}`
|
||||
? never
|
||||
: "" extends A & ""
|
||||
? never
|
||||
: A
|
||||
? never
|
||||
: A
|
||||
|
||||
export type ConfigRes = {
|
||||
/** This should be the previous config, that way during set config we start with the previous */
|
||||
|
||||
@@ -8,18 +8,22 @@ export const execFile = promisify(cp.execFile)
|
||||
export class Overlay {
|
||||
private constructor(
|
||||
readonly effects: T.Effects,
|
||||
readonly imageId: string,
|
||||
readonly rootfs: string,
|
||||
) {}
|
||||
static async of(effects: T.Effects, imageId: string) {
|
||||
const rootfs = await effects.createOverlayedImage({ imageId })
|
||||
|
||||
for (const dirPart of ["dev", "sys", "proc", "run"] as const) {
|
||||
const dir = await fs.mkdir(`${rootfs}/${dirPart}`, { recursive: true })
|
||||
if (!dir) break
|
||||
await execFile("mount", ["--bind", `/${dirPart}`, dir])
|
||||
await fs.mkdir(`${rootfs}/${dirPart}`, { recursive: true })
|
||||
await execFile("mount", [
|
||||
"--rbind",
|
||||
`/${dirPart}`,
|
||||
`${rootfs}/${dirPart}`,
|
||||
])
|
||||
}
|
||||
|
||||
return new Overlay(effects, rootfs)
|
||||
return new Overlay(effects, imageId, rootfs)
|
||||
}
|
||||
|
||||
async mount(options: MountOptions, path: string): Promise<Overlay> {
|
||||
@@ -55,20 +59,59 @@ export class Overlay {
|
||||
command: string[],
|
||||
options?: CommandOptions,
|
||||
): Promise<{ stdout: string | Buffer; stderr: string | Buffer }> {
|
||||
return await execFile("chroot", [this.rootfs, ...command], options)
|
||||
let extra: string[] = []
|
||||
if (options?.cwd) {
|
||||
extra.push(`--workdir=${options.cwd}`)
|
||||
delete options.cwd
|
||||
}
|
||||
if (options?.user) {
|
||||
extra.push(`--user=${options.user}`)
|
||||
delete options.user
|
||||
}
|
||||
return await execFile(
|
||||
"start-cli",
|
||||
[
|
||||
"chroot",
|
||||
`--env=/media/startos/env/${this.imageId}.env`,
|
||||
...extra,
|
||||
this.rootfs,
|
||||
...command,
|
||||
],
|
||||
options,
|
||||
)
|
||||
}
|
||||
|
||||
spawn(
|
||||
command: string[],
|
||||
options?: CommandOptions,
|
||||
): cp.ChildProcessWithoutNullStreams {
|
||||
return cp.spawn("chroot", [this.rootfs, ...command], options)
|
||||
let extra: string[] = []
|
||||
if (options?.cwd) {
|
||||
extra.push(`--workdir=${options.cwd}`)
|
||||
delete options.cwd
|
||||
}
|
||||
if (options?.user) {
|
||||
extra.push(`--user=${options.user}`)
|
||||
delete options.user
|
||||
}
|
||||
return cp.spawn(
|
||||
"start-cli",
|
||||
[
|
||||
"chroot",
|
||||
`--env=/media/startos/env/${this.imageId}.env`,
|
||||
...extra,
|
||||
this.rootfs,
|
||||
...command,
|
||||
],
|
||||
options,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export type CommandOptions = {
|
||||
env?: { [variable: string]: string }
|
||||
cwd?: string
|
||||
user?: string
|
||||
}
|
||||
|
||||
export type MountOptions =
|
||||
|
||||
@@ -69,8 +69,8 @@ const addressHostToUrl = (
|
||||
const scheme = host.endsWith(".onion")
|
||||
? options.scheme
|
||||
: options.addSsl
|
||||
? options.addSsl.scheme
|
||||
: options.scheme // TODO: encode whether hostname transport is "secure"?
|
||||
? options.addSsl.scheme
|
||||
: options.scheme // TODO: encode whether hostname transport is "secure"?
|
||||
return `${scheme ? `${scheme}//` : ""}${
|
||||
username ? `${username}@` : ""
|
||||
}${host}${suffix}`
|
||||
|
||||
@@ -7,7 +7,7 @@ import "./deepEqual"
|
||||
import "./deepMerge"
|
||||
import "./Overlay"
|
||||
import "./once"
|
||||
import { utils } from "./utils"
|
||||
import * as utils from "./utils"
|
||||
import { SDKManifest } from "../manifest/ManifestTypes"
|
||||
|
||||
// prettier-ignore
|
||||
@@ -23,7 +23,7 @@ export const isKnownError = (e: unknown): e is T.KnownError =>
|
||||
|
||||
declare const affine: unique symbol
|
||||
|
||||
export const createUtils = utils
|
||||
export const createUtils = utils.createUtils
|
||||
export const createMainUtils = <Manifest extends SDKManifest, Store>(
|
||||
effects: T.Effects,
|
||||
) => createUtils<Manifest, Store, {}>(effects)
|
||||
|
||||
@@ -141,7 +141,7 @@ export type Utils<
|
||||
) => Promise<void>
|
||||
}
|
||||
}
|
||||
export const utils = <
|
||||
export const createUtils = <
|
||||
Manifest extends SDKManifest,
|
||||
Store = never,
|
||||
WrapperOverWrite = { const: never },
|
||||
|
||||
@@ -1,15 +1,10 @@
|
||||
{
|
||||
"include": [
|
||||
"./lib/**/*.ts",
|
||||
"scripts/oldSpecToBuilder.ts"
|
||||
],
|
||||
"inputs": [
|
||||
"./lib/index.ts"
|
||||
],
|
||||
"include": ["./lib/**/*.ts", "scripts/oldSpecToBuilder.ts"],
|
||||
"inputs": ["./lib/index.ts"],
|
||||
"compilerOptions": {
|
||||
"target": "es2022",
|
||||
"module": "es2022",
|
||||
"moduleResolution": "node",
|
||||
"module": "Node16",
|
||||
"moduleResolution": "Node16",
|
||||
"declaration": true,
|
||||
"outDir": "./dist/",
|
||||
"esModuleInterop": true,
|
||||
|
||||
Reference in New Issue
Block a user