mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-26 10:21:52 +00:00
delegate pointer removal to config transformer
This commit is contained in:
@@ -45,6 +45,7 @@ import {
|
||||
OldConfigSpec,
|
||||
matchOldConfigSpec,
|
||||
transformConfigSpec,
|
||||
transformNewConfigToOld,
|
||||
transformOldConfigToNew,
|
||||
} from "./transformConfigSpec"
|
||||
import { MainEffects } from "@start9labs/start-sdk/cjs/lib/StartSdk"
|
||||
@@ -101,6 +102,11 @@ const matchSetResult = object(
|
||||
["depends-on", "dependsOn"],
|
||||
)
|
||||
|
||||
type OldGetConfigRes = {
|
||||
config?: null | Record<string, unknown>
|
||||
spec: OldConfigSpec
|
||||
}
|
||||
|
||||
export type PackagePropertiesV2 = {
|
||||
[name: string]: PackagePropertyObject | PackagePropertyString
|
||||
}
|
||||
@@ -546,14 +552,12 @@ export class SystemForEmbassy implements System {
|
||||
effects: Effects,
|
||||
timeoutMs: number | null,
|
||||
): Promise<T.ConfigRes> {
|
||||
return this.getConfigUncleaned(effects, timeoutMs)
|
||||
.then(removePointers)
|
||||
.then(convertToNewConfig)
|
||||
return this.getConfigUncleaned(effects, timeoutMs).then(convertToNewConfig)
|
||||
}
|
||||
private async getConfigUncleaned(
|
||||
effects: Effects,
|
||||
timeoutMs: number | null,
|
||||
): Promise<T.ConfigRes> {
|
||||
): Promise<OldGetConfigRes> {
|
||||
const config = this.manifest.config?.get
|
||||
if (!config) return { spec: {} }
|
||||
if (config.type === "docker") {
|
||||
@@ -590,13 +594,14 @@ export class SystemForEmbassy implements System {
|
||||
newConfigWithoutPointers: unknown,
|
||||
timeoutMs: number | null,
|
||||
): Promise<void> {
|
||||
const newConfig = structuredClone(newConfigWithoutPointers)
|
||||
await updateConfig(
|
||||
effects,
|
||||
this.manifest,
|
||||
await this.getConfigUncleaned(effects, timeoutMs).then((x) => x.spec),
|
||||
newConfig,
|
||||
const spec = await this.getConfigUncleaned(effects, timeoutMs).then(
|
||||
(x) => x.spec,
|
||||
)
|
||||
const newConfig = transformNewConfigToOld(
|
||||
spec,
|
||||
structuredClone(newConfigWithoutPointers as Record<string, unknown>),
|
||||
)
|
||||
await updateConfig(effects, this.manifest, spec, newConfig)
|
||||
const setConfigValue = this.manifest.config?.set
|
||||
if (!setConfigValue) return
|
||||
if (setConfigValue.type === "docker") {
|
||||
@@ -895,14 +900,6 @@ export class SystemForEmbassy implements System {
|
||||
})) as any
|
||||
}
|
||||
}
|
||||
async function removePointers(value: T.ConfigRes): Promise<T.ConfigRes> {
|
||||
const startingSpec = structuredClone(value.spec)
|
||||
const config =
|
||||
value.config && cleanConfigFromPointers(value.config, startingSpec)
|
||||
const spec = cleanSpecOfPointers(startingSpec)
|
||||
|
||||
return { config, spec }
|
||||
}
|
||||
|
||||
const matchPointer = object({
|
||||
type: literal("pointer"),
|
||||
@@ -962,27 +959,6 @@ type CleanConfigFromPointers<C, S> =
|
||||
} :
|
||||
null
|
||||
|
||||
function cleanConfigFromPointers<C, S>(
|
||||
config: C,
|
||||
spec: S,
|
||||
): CleanConfigFromPointers<C, S> {
|
||||
const newConfig = {} as CleanConfigFromPointers<C, S>
|
||||
|
||||
if (!(object.test(config) && object.test(spec)) || newConfig == null)
|
||||
return null as CleanConfigFromPointers<C, S>
|
||||
|
||||
for (const key of Object.keys(spec)) {
|
||||
if (!isKeyOf(key, spec)) continue
|
||||
if (!isKeyOf(key, config)) continue
|
||||
const partSpec = spec[key]
|
||||
if (matchPointer.test(partSpec)) continue
|
||||
;(newConfig as any)[key] = matchSpec.test(partSpec)
|
||||
? cleanConfigFromPointers(config[key], partSpec.spec)
|
||||
: config[key]
|
||||
}
|
||||
return newConfig as CleanConfigFromPointers<C, S>
|
||||
}
|
||||
|
||||
async function updateConfig(
|
||||
effects: Effects,
|
||||
manifest: Manifest,
|
||||
@@ -1081,7 +1057,9 @@ function extractServiceInterfaceId(manifest: Manifest, specInterface: string) {
|
||||
const serviceInterfaceId = `${specInterface}-${internalPort}`
|
||||
return serviceInterfaceId
|
||||
}
|
||||
async function convertToNewConfig(value: T.ConfigRes): Promise<T.ConfigRes> {
|
||||
async function convertToNewConfig(
|
||||
value: OldGetConfigRes,
|
||||
): Promise<T.ConfigRes> {
|
||||
const valueSpec: OldConfigSpec = matchOldConfigSpec.unsafeCast(value.spec)
|
||||
const spec = transformConfigSpec(valueSpec)
|
||||
if (!value.config) return { spec, config: null }
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
deferred,
|
||||
every,
|
||||
nill,
|
||||
literal,
|
||||
} from "ts-matches"
|
||||
|
||||
export function transformConfigSpec(oldSpec: OldConfigSpec): CT.InputSpec {
|
||||
@@ -38,7 +39,7 @@ export function transformConfigSpec(oldSpec: OldConfigSpec): CT.InputSpec {
|
||||
values: oldVal.values.reduce(
|
||||
(obj, curr) => ({
|
||||
...obj,
|
||||
[curr]: oldVal["value-names"][curr],
|
||||
[curr]: oldVal["value-names"][curr] || curr,
|
||||
}),
|
||||
{},
|
||||
),
|
||||
@@ -109,7 +110,7 @@ export function transformConfigSpec(oldSpec: OldConfigSpec): CT.InputSpec {
|
||||
inputmode: "text",
|
||||
placeholder: oldVal.placeholder || null,
|
||||
}
|
||||
} else {
|
||||
} else if (oldVal.type === "union") {
|
||||
newVal = {
|
||||
type: "union",
|
||||
name: oldVal.tag.name,
|
||||
@@ -119,7 +120,7 @@ export function transformConfigSpec(oldSpec: OldConfigSpec): CT.InputSpec {
|
||||
(obj, [id, spec]) => ({
|
||||
...obj,
|
||||
[id]: {
|
||||
name: oldVal.tag["variant-names"][id],
|
||||
name: oldVal.tag["variant-names"][id] || id,
|
||||
spec: transformConfigSpec(matchOldConfigSpec.unsafeCast(spec)),
|
||||
},
|
||||
}),
|
||||
@@ -130,6 +131,10 @@ export function transformConfigSpec(oldSpec: OldConfigSpec): CT.InputSpec {
|
||||
default: oldVal.default,
|
||||
immutable: false,
|
||||
}
|
||||
} else if (oldVal.type === "pointer") {
|
||||
return inputSpec
|
||||
} else {
|
||||
throw new Error(`unknown spec ${JSON.stringify(oldVal)}`)
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -175,6 +180,10 @@ export function transformOldConfigToNew(
|
||||
)
|
||||
}
|
||||
|
||||
if (isPointer(val)) {
|
||||
return obj
|
||||
}
|
||||
|
||||
return {
|
||||
...obj,
|
||||
[key]: newVal,
|
||||
@@ -201,7 +210,7 @@ export function transformNewConfigToOld(
|
||||
[val.tag.id]: config[key].selection,
|
||||
...transformNewConfigToOld(
|
||||
matchOldConfigSpec.unsafeCast(val.variants[config[key].selection]),
|
||||
config[key].unionSelectValue,
|
||||
config[key].value,
|
||||
),
|
||||
}
|
||||
}
|
||||
@@ -313,6 +322,10 @@ function isList(val: OldValueSpec): val is OldValueSpecList {
|
||||
return val.type === "list"
|
||||
}
|
||||
|
||||
function isPointer(val: OldValueSpec): val is OldValueSpecPointer {
|
||||
return val.type === "pointer"
|
||||
}
|
||||
|
||||
function isEnumList(
|
||||
val: OldValueSpecList,
|
||||
): val is OldValueSpecList & { subtype: "enum" } {
|
||||
@@ -522,6 +535,28 @@ const matchOldValueSpecList = every(
|
||||
)
|
||||
type OldValueSpecList = typeof matchOldValueSpecList._TYPE
|
||||
|
||||
const matchOldValueSpecPointer = every(
|
||||
object({
|
||||
type: literal("pointer"),
|
||||
}),
|
||||
anyOf(
|
||||
object({
|
||||
subtype: literal("package"),
|
||||
target: literals("tor-key", "tor-address", "lan-address"),
|
||||
"package-id": string,
|
||||
interface: string,
|
||||
}),
|
||||
object({
|
||||
subtype: literal("package"),
|
||||
target: literals("config"),
|
||||
"package-id": string,
|
||||
selector: string,
|
||||
multi: boolean,
|
||||
}),
|
||||
),
|
||||
)
|
||||
type OldValueSpecPointer = typeof matchOldValueSpecPointer._TYPE
|
||||
|
||||
export const matchOldValueSpec = anyOf(
|
||||
matchOldValueSpecString,
|
||||
matchOldValueSpecNumber,
|
||||
@@ -530,6 +565,7 @@ export const matchOldValueSpec = anyOf(
|
||||
matchOldValueSpecEnum,
|
||||
matchOldValueSpecList,
|
||||
matchOldValueSpecUnion,
|
||||
matchOldValueSpecPointer,
|
||||
)
|
||||
type OldValueSpec = typeof matchOldValueSpec._TYPE
|
||||
|
||||
|
||||
Reference in New Issue
Block a user