feat: New actions

This commit is contained in:
BluJ
2023-05-03 13:15:51 -06:00
parent f4c93438f8
commit a71b2f9f82
5 changed files with 57 additions and 24 deletions

View File

@@ -11,16 +11,15 @@ export class CreatedAction<
Type extends Record<string, any> = ExtractConfigType<ConfigType>, Type extends Record<string, any> = ExtractConfigType<ConfigType>,
> { > {
private constructor( private constructor(
public readonly myMetaData: Omit<ActionMetaData, "input"> & { public readonly myMetaData: ActionMetaData,
input: Config<Type, WrapperData>
},
readonly fn: (options: { readonly fn: (options: {
effects: Effects effects: Effects
utils: Utils<WrapperData> utils: Utils<WrapperData>
input: Type input: Type
}) => Promise<ActionResult>, }) => Promise<ActionResult>,
readonly input: Config<Type, WrapperData> | Config<Type, never>,
) {} ) {}
private validator = this.myMetaData.input.validator public validator = this.input.validator
static of< static of<
WrapperData, WrapperData,
@@ -36,7 +35,8 @@ export class CreatedAction<
input: Type input: Type
}) => Promise<ActionResult>, }) => Promise<ActionResult>,
) { ) {
return new CreatedAction<WrapperData, ConfigType, Type>(metaData, fn) const { input, ...rest } = metaData
return new CreatedAction<WrapperData, ConfigType, Type>(rest, fn, input)
} }
exportedAction: ExportedAction = ({ effects, input }) => { exportedAction: ExportedAction = ({ effects, input }) => {
@@ -47,16 +47,19 @@ export class CreatedAction<
}) })
} }
async exportAction(effects: Effects) { run = async ({ effects, input }: { effects: Effects; input?: Type }) => {
const myUtils = utils<WrapperData>(effects) return this.fn({
const metaData = { effects,
...this.myMetaData, utils: utils<WrapperData>(effects),
input: await this.myMetaData.input.build({ input: this.validator.unsafeCast(input),
effects, })
utils: myUtils, }
}),
} async getConfig({ effects }: { effects: Effects }) {
await effects.exportAction(metaData) return this.input.build({
effects,
utils: utils<WrapperData>(effects) as any,
})
} }
} }

View File

@@ -1,15 +1,19 @@
import { Effects, ExpectedExports, ExportedAction } from "../types" import { Effects, ExpectedExports, ExportedAction } from "../types"
import { ActionMetaData } from "../types" import { ActionMetaData } from "../types"
import { once } from "../util/once"
import { CreatedAction } from "./createAction" import { CreatedAction } from "./createAction"
export function setupActions(...createdActions: CreatedAction<any, any>[]) { export function setupActions(...createdActions: CreatedAction<any, any>[]) {
const myActions = once(() => {
const actions: Record<string, CreatedAction<any, any>> = {}
for (const action of createdActions) {
actions[action.myMetaData.id] = action
}
return actions
})
return { return {
get actions() { get actions() {
const actions: Record<string, ExportedAction> = {} return myActions()
for (const action of createdActions) {
actions[action.myMetaData.id] = action.exportedAction
}
return actions
}, },
get actionsMetadata() { get actionsMetadata() {
return createdActions.map((x) => x.myMetaData) return createdActions.map((x) => x.myMetaData)

View File

@@ -627,12 +627,15 @@ export class Value<Type, WD> {
static filteredUnion<WrapperData = never>( static filteredUnion<WrapperData = never>(
getDisabledFn: LazyBuild<WrapperData, string[]>, getDisabledFn: LazyBuild<WrapperData, string[]>,
) { ) {
return <Type extends Record<string, any>>( return <
Required extends RequiredDefault<string>,
Type extends Record<string, any>,
>(
a: { a: {
name: string name: string
description?: string | null description?: string | null
warning?: string | null warning?: string | null
required: RequiredDefault<string> required: Required
default?: string | null default?: string | null
}, },
aVariants: Variants<Type, WrapperData> | Variants<Type, never>, aVariants: Variants<Type, WrapperData> | Variants<Type, never>,

View File

@@ -59,3 +59,4 @@ export const smtpConfig = Value.filteredUnion(async ({ effects, utils }) => {
}, },
}), }),
) )
type test = typeof smtpConfig.validator._TYPE

View File

@@ -43,7 +43,10 @@ export namespace ExpectedExports {
* service starting, and that file would indicate that it would rescan all the data. * service starting, and that file would indicate that it would rescan all the data.
*/ */
export type actions = { export type actions = {
[id: string]: ExportedAction [id: string]: {
run: ExportedAction
getConfig: (options: { effects: Effects }) => Promise<InputSpec>
}
} }
/** /**
@@ -155,7 +158,6 @@ export type ActionMetaData = {
name: string name: string
description: string description: string
id: string id: string
input: null | InputSpec
runningOnly: boolean runningOnly: boolean
/** /**
* So the ordering of the actions is by alphabetical order of the group, then followed by the alphabetical of the actions * So the ordering of the actions is by alphabetical order of the group, then followed by the alphabetical of the actions
@@ -424,6 +426,26 @@ export type Effects = {
exists(packageId: PackageId): Promise<boolean> exists(packageId: PackageId): Promise<boolean>
/** Exists could be useful during the runtime to know if some service is running, option dep */ /** Exists could be useful during the runtime to know if some service is running, option dep */
running(packageId: PackageId): Promise<boolean> running(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: {
bind: {
/** Optional, default is 0.0.0.0 */
ip?: string
port: number
ssl: boolean
}
dst: {
/** Optional: default is 127.0.0.1 */
ip?: string // optional, default 127.0.0.1
port: number
ssl: boolean
}
http: {
// optional, will do TCP layer proxy only if not present
headers: (headers: Record<string, string>) => Record<string, string>
}
}): Promise<{ stop(): Promise<void> }>
restart(): void restart(): void
shutdown(): void shutdown(): void
} }