delegate pointer removal to config transformer

This commit is contained in:
Aiden McClelland
2024-07-26 14:47:43 -06:00
parent 698bdd619f
commit 10ede0d21c
2 changed files with 58 additions and 44 deletions

View File

@@ -45,6 +45,7 @@ import {
OldConfigSpec, OldConfigSpec,
matchOldConfigSpec, matchOldConfigSpec,
transformConfigSpec, transformConfigSpec,
transformNewConfigToOld,
transformOldConfigToNew, transformOldConfigToNew,
} from "./transformConfigSpec" } from "./transformConfigSpec"
import { MainEffects } from "@start9labs/start-sdk/cjs/lib/StartSdk" import { MainEffects } from "@start9labs/start-sdk/cjs/lib/StartSdk"
@@ -101,6 +102,11 @@ const matchSetResult = object(
["depends-on", "dependsOn"], ["depends-on", "dependsOn"],
) )
type OldGetConfigRes = {
config?: null | Record<string, unknown>
spec: OldConfigSpec
}
export type PackagePropertiesV2 = { export type PackagePropertiesV2 = {
[name: string]: PackagePropertyObject | PackagePropertyString [name: string]: PackagePropertyObject | PackagePropertyString
} }
@@ -546,14 +552,12 @@ export class SystemForEmbassy implements System {
effects: Effects, effects: Effects,
timeoutMs: number | null, timeoutMs: number | null,
): Promise<T.ConfigRes> { ): Promise<T.ConfigRes> {
return this.getConfigUncleaned(effects, timeoutMs) return this.getConfigUncleaned(effects, timeoutMs).then(convertToNewConfig)
.then(removePointers)
.then(convertToNewConfig)
} }
private async getConfigUncleaned( private async getConfigUncleaned(
effects: Effects, effects: Effects,
timeoutMs: number | null, timeoutMs: number | null,
): Promise<T.ConfigRes> { ): Promise<OldGetConfigRes> {
const config = this.manifest.config?.get const config = this.manifest.config?.get
if (!config) return { spec: {} } if (!config) return { spec: {} }
if (config.type === "docker") { if (config.type === "docker") {
@@ -590,13 +594,14 @@ export class SystemForEmbassy implements System {
newConfigWithoutPointers: unknown, newConfigWithoutPointers: unknown,
timeoutMs: number | null, timeoutMs: number | null,
): Promise<void> { ): Promise<void> {
const newConfig = structuredClone(newConfigWithoutPointers) const spec = await this.getConfigUncleaned(effects, timeoutMs).then(
await updateConfig( (x) => x.spec,
effects,
this.manifest,
await this.getConfigUncleaned(effects, timeoutMs).then((x) => x.spec),
newConfig,
) )
const newConfig = transformNewConfigToOld(
spec,
structuredClone(newConfigWithoutPointers as Record<string, unknown>),
)
await updateConfig(effects, this.manifest, spec, newConfig)
const setConfigValue = this.manifest.config?.set const setConfigValue = this.manifest.config?.set
if (!setConfigValue) return if (!setConfigValue) return
if (setConfigValue.type === "docker") { if (setConfigValue.type === "docker") {
@@ -895,14 +900,6 @@ export class SystemForEmbassy implements System {
})) as any })) 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({ const matchPointer = object({
type: literal("pointer"), type: literal("pointer"),
@@ -962,27 +959,6 @@ type CleanConfigFromPointers<C, S> =
} : } :
null 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( async function updateConfig(
effects: Effects, effects: Effects,
manifest: Manifest, manifest: Manifest,
@@ -1081,7 +1057,9 @@ function extractServiceInterfaceId(manifest: Manifest, specInterface: string) {
const serviceInterfaceId = `${specInterface}-${internalPort}` const serviceInterfaceId = `${specInterface}-${internalPort}`
return serviceInterfaceId 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 valueSpec: OldConfigSpec = matchOldConfigSpec.unsafeCast(value.spec)
const spec = transformConfigSpec(valueSpec) const spec = transformConfigSpec(valueSpec)
if (!value.config) return { spec, config: null } if (!value.config) return { spec, config: null }

View File

@@ -12,6 +12,7 @@ import {
deferred, deferred,
every, every,
nill, nill,
literal,
} from "ts-matches" } from "ts-matches"
export function transformConfigSpec(oldSpec: OldConfigSpec): CT.InputSpec { export function transformConfigSpec(oldSpec: OldConfigSpec): CT.InputSpec {
@@ -38,7 +39,7 @@ export function transformConfigSpec(oldSpec: OldConfigSpec): CT.InputSpec {
values: oldVal.values.reduce( values: oldVal.values.reduce(
(obj, curr) => ({ (obj, curr) => ({
...obj, ...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", inputmode: "text",
placeholder: oldVal.placeholder || null, placeholder: oldVal.placeholder || null,
} }
} else { } else if (oldVal.type === "union") {
newVal = { newVal = {
type: "union", type: "union",
name: oldVal.tag.name, name: oldVal.tag.name,
@@ -119,7 +120,7 @@ export function transformConfigSpec(oldSpec: OldConfigSpec): CT.InputSpec {
(obj, [id, spec]) => ({ (obj, [id, spec]) => ({
...obj, ...obj,
[id]: { [id]: {
name: oldVal.tag["variant-names"][id], name: oldVal.tag["variant-names"][id] || id,
spec: transformConfigSpec(matchOldConfigSpec.unsafeCast(spec)), spec: transformConfigSpec(matchOldConfigSpec.unsafeCast(spec)),
}, },
}), }),
@@ -130,6 +131,10 @@ export function transformConfigSpec(oldSpec: OldConfigSpec): CT.InputSpec {
default: oldVal.default, default: oldVal.default,
immutable: false, immutable: false,
} }
} else if (oldVal.type === "pointer") {
return inputSpec
} else {
throw new Error(`unknown spec ${JSON.stringify(oldVal)}`)
} }
return { return {
@@ -175,6 +180,10 @@ export function transformOldConfigToNew(
) )
} }
if (isPointer(val)) {
return obj
}
return { return {
...obj, ...obj,
[key]: newVal, [key]: newVal,
@@ -201,7 +210,7 @@ export function transformNewConfigToOld(
[val.tag.id]: config[key].selection, [val.tag.id]: config[key].selection,
...transformNewConfigToOld( ...transformNewConfigToOld(
matchOldConfigSpec.unsafeCast(val.variants[config[key].selection]), 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" return val.type === "list"
} }
function isPointer(val: OldValueSpec): val is OldValueSpecPointer {
return val.type === "pointer"
}
function isEnumList( function isEnumList(
val: OldValueSpecList, val: OldValueSpecList,
): val is OldValueSpecList & { subtype: "enum" } { ): val is OldValueSpecList & { subtype: "enum" } {
@@ -522,6 +535,28 @@ const matchOldValueSpecList = every(
) )
type OldValueSpecList = typeof matchOldValueSpecList._TYPE 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( export const matchOldValueSpec = anyOf(
matchOldValueSpecString, matchOldValueSpecString,
matchOldValueSpecNumber, matchOldValueSpecNumber,
@@ -530,6 +565,7 @@ export const matchOldValueSpec = anyOf(
matchOldValueSpecEnum, matchOldValueSpecEnum,
matchOldValueSpecList, matchOldValueSpecList,
matchOldValueSpecUnion, matchOldValueSpecUnion,
matchOldValueSpecPointer,
) )
type OldValueSpec = typeof matchOldValueSpec._TYPE type OldValueSpec = typeof matchOldValueSpec._TYPE